Commit de340512 authored by Tooru Fujisawa's avatar Tooru Fujisawa
Browse files

Bug 1779988 - Part 2: Add ESLint rule that rejects multiple...

Bug 1779988 - Part 2: Add ESLint rule that rejects multiple `ChromeUtils.defineESModuleGetters` call on the same object. r=Standard8

Differential Revision: https://phabricator.services.mozilla.com/D152880
parent bf159ca1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ The plugin implements the following rules:
   eslint-plugin-mozilla/reject-importGlobalProperties
   eslint-plugin-mozilla/reject-lazy-imports-into-globals
   eslint-plugin-mozilla/reject-mixing-eager-and-lazy
   eslint-plugin-mozilla/reject-multiple-getters-calls
   eslint-plugin-mozilla/reject-osfile
   eslint-plugin-mozilla/reject-relative-requires
   eslint-plugin-mozilla/reject-requires-await
+27 −0
Original line number Diff line number Diff line
reject-multiple-getters-calls
=============================

Rejects multiple calls on ``ChromeUtils.defineESModuleGetters`` for the same
target in the same context.

Examples of incorrect code for this rule:
-----------------------------------------

.. code-block:: js

    ChromeUtils.defineESModuleGetters(lazy, {
      AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
    });
    ChromeUtils.defineESModuleGetters(lazy, {
      PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
    });

Examples of correct code for this rule:
---------------------------------------

.. code-block:: js

    ChromeUtils.defineESModuleGetters(lazy, {
      AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
      PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
    });
+1 −0
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ module.exports = {
    "mozilla/reject-addtask-only": "error",
    "mozilla/reject-chromeutils-import-params": "error",
    "mozilla/reject-importGlobalProperties": ["error", "allownonwebidl"],
    "mozilla/reject-multiple-getters-calls": "error",
    "mozilla/reject-osfile": "warn",
    "mozilla/reject-scriptableunicodeconverter": "warn",
    "mozilla/rejects-requires-await": "error",
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ module.exports = {
    "reject-importGlobalProperties": require("../lib/rules/reject-importGlobalProperties"),
    "reject-lazy-imports-into-globals": require("../lib/rules/reject-lazy-imports-into-globals"),
    "reject-mixing-eager-and-lazy": require("../lib/rules/reject-mixing-eager-and-lazy"),
    "reject-multiple-getters-calls": require("../lib/rules/reject-multiple-getters-calls"),
    "reject-osfile": require("../lib/rules/reject-osfile"),
    "reject-scriptableunicodeconverter": require("../lib/rules/reject-scriptableunicodeconverter"),
    "reject-relative-requires": require("../lib/rules/reject-relative-requires"),
+81 −0
Original line number Diff line number Diff line
/**
 * 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 findStatement(node) {
  while (node && node.type !== "ExpressionStatement") {
    node = node.parent;
  }

  return node;
}

function isIdentifier(node, id) {
  return node && node.type === "Identifier" && node.name === id;
}

module.exports = {
  meta: {
    docs: {
      url:
        "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/reject-multiple-getters-calls.html",
    },
    messages: {
      rejectMultipleCalls:
        "ChromeUtils.defineESModuleGetters is already called for {{target}} in the same context. Please merge those calls",
    },
    type: "suggestion",
  },

  create(context) {
    const parentToTargets = new Map();

    return {
      CallExpression(node) {
        let callee = node.callee;
        if (
          callee.type === "MemberExpression" &&
          isIdentifier(callee.object, "ChromeUtils") &&
          isIdentifier(callee.property, "defineESModuleGetters")
        ) {
          const stmt = findStatement(node);
          if (!stmt) {
            return;
          }

          let target;
          try {
            target = helpers.getASTSource(node.arguments[0]);
          } catch (e) {
            return;
          }

          const parent = stmt.parent;
          let targets;
          if (parentToTargets.has(parent)) {
            targets = parentToTargets.get(parent);
          } else {
            targets = new Set();
            parentToTargets.set(parent, targets);
          }

          if (targets.has(target)) {
            context.report({
              node,
              messageId: "rejectMultipleCalls",
              data: { target },
            });
          }

          targets.add(target);
        }
      },
    };
  },
};
Loading