| 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            );          }        }      },    };  },};
 |