123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /**
- * @fileoverview Reject use of lazy getters for modules that's loaded early in
- * the startup process and not necessarily be lazy.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- "use strict";
- const helpers = require("../helpers");
- function isIdentifier(node, id) {
- return node.type === "Identifier" && node.name === id;
- }
- function isString(node) {
- return node.type === "Literal" && typeof node.value === "string";
- }
- function checkMixed(loadedModules, context, node, type, resourceURI) {
- if (!loadedModules.has(resourceURI)) {
- loadedModules.set(resourceURI, type);
- }
- if (loadedModules.get(resourceURI) === type) {
- return;
- }
- context.report({
- node,
- messageId: "mixedEagerAndLazy",
- data: { uri: resourceURI },
- });
- }
- module.exports = {
- meta: {
- docs: {
- url:
- "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-mixed-eager-and-lazy.html",
- },
- messages: {
- mixedEagerAndLazy:
- 'Module "{{uri}}" is loaded eagerly, and should not be used for lazy getter.',
- },
- type: "problem",
- },
- create(context) {
- const loadedModules = new Map();
- return {
- ImportDeclaration(node) {
- const resourceURI = node.source.value;
- checkMixed(loadedModules, context, node, "eager", resourceURI);
- },
- CallExpression(node) {
- if (node.callee.type !== "MemberExpression") {
- return;
- }
- let callerSource;
- try {
- callerSource = helpers.getASTSource(node.callee);
- } catch (e) {
- return;
- }
- if (
- (callerSource === "ChromeUtils.import" ||
- callerSource === "ChromeUtils.importESModule") &&
- helpers.getIsTopLevelAndUnconditionallyExecuted(
- context.getAncestors()
- )
- ) {
- if (node.arguments.length < 1) {
- return;
- }
- const resourceURINode = node.arguments[0];
- if (!isString(resourceURINode)) {
- return;
- }
- checkMixed(
- loadedModules,
- context,
- node,
- "eager",
- resourceURINode.value
- );
- }
- if (
- callerSource === "XPCOMUtils.defineLazyModuleGetter" ||
- callerSource === "ChromeUtils.defineModuleGetter"
- ) {
- if (node.arguments.length < 3) {
- return;
- }
- if (!isIdentifier(node.arguments[0], "lazy")) {
- return;
- }
- const resourceURINode = node.arguments[2];
- if (!isString(resourceURINode)) {
- return;
- }
- checkMixed(
- loadedModules,
- context,
- node,
- "lazy",
- resourceURINode.value
- );
- } else if (
- callerSource === "XPCOMUtils.defineLazyModuleGetters" ||
- callerSource === "ChromeUtils.defineESModuleGetters"
- ) {
- if (node.arguments.length < 2) {
- return;
- }
- if (!isIdentifier(node.arguments[0], "lazy")) {
- return;
- }
- const obj = node.arguments[1];
- if (obj.type !== "ObjectExpression") {
- return;
- }
- for (let prop of obj.properties) {
- if (prop.type !== "Property") {
- continue;
- }
- if (prop.kind !== "init") {
- continue;
- }
- const resourceURINode = prop.value;
- if (!isString(resourceURINode)) {
- continue;
- }
- checkMixed(
- loadedModules,
- context,
- node,
- "lazy",
- resourceURINode.value
- );
- }
- }
- },
- };
- },
- };
|