Skip to content

Commit

Permalink
Bug 1608272 - Extend an ESLint rule to disallow 'this' as the second …
Browse files Browse the repository at this point in the history
…argument to ChromeUtils.import. r=Gijs

Depends on D104684

Differential Revision: https://phabricator.services.mozilla.com/D104685
  • Loading branch information
Standard8 committed Feb 11, 2021
1 parent 3ef6aca commit 67bf517
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 89 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ module.exports = {
"toolkit/mozapps/installer/precompile_cache.js",
],
rules: {
"mozilla/reject-chromeutils-import-null": "off",
"mozilla/reject-chromeutils-import-params": "off",
},
},
],
Expand Down
1 change: 1 addition & 0 deletions docs/code-quality/lint/linters/eslint-plugin-mozilla.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ The plugin implements the following rules:
eslint-plugin-mozilla/no-define-cc-etc
eslint-plugin-mozilla/no-throw-cr-literal
eslint-plugin-mozilla/no-useless-parameters
eslint-plugin-mozilla/reject-chromeutils-import-params
eslint-plugin-mozilla/use-chromeutils-import

avoid-removeChild
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
================================
reject-chromeutils-import-params
================================

``ChromeUtils.import`` can be called with two arguments, however these are now
largely deprecated.

The use of object destructuring is preferred over the second parameter being
``this``.

Using explicit exports is preferred over the second parameter being ``null``.

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

.. code-block:: js
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
ChromeUtils.import("resource://gre/modules/Services.jsm", null);
Examples of correct code for this rule:
---------------------------------------

.. code-block:: js
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ module.exports = {
"mozilla/no-useless-removeEventListener": "error",
"mozilla/prefer-boolean-length-check": "error",
"mozilla/prefer-formatValues": "error",
"mozilla/reject-chromeutils-import-null": "error",
"mozilla/reject-chromeutils-import-params": "error",
"mozilla/reject-importGlobalProperties": ["error", "allownonwebidl"],
"mozilla/rejects-requires-await": "error",
"mozilla/use-cc-etc": "error",
Expand Down
2 changes: 1 addition & 1 deletion tools/lint/eslint/eslint-plugin-mozilla/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ module.exports = {
"no-useless-run-test": require("../lib/rules/no-useless-run-test"),
"prefer-boolean-length-check": require("../lib/rules/prefer-boolean-length-check"),
"prefer-formatValues": require("../lib/rules/prefer-formatValues"),
"reject-chromeutils-import-null": require("../lib/rules/reject-chromeutils-import-null"),
"reject-chromeutils-import-params": require("../lib/rules/reject-chromeutils-import-params"),
"reject-importGlobalProperties": require("../lib/rules/reject-importGlobalProperties"),
"reject-relative-requires": require("../lib/rules/reject-relative-requires"),
"reject-some-requires": require("../lib/rules/reject-some-requires"),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* @fileoverview Reject calls to ChromeUtils.import(..., null). This allows to
* retrieve the global object for the JSM, instead we should rely on explicitly
* exported symbols.
*
* 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";

// -----------------------------------------------------------------------------
// Rule Definition
// -----------------------------------------------------------------------------

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

module.exports = function(context) {
// ---------------------------------------------------------------------------
// Public
// --------------------------------------------------------------------------

return {
CallExpression(node) {
let { callee } = node;
if (
isIdentifier(callee.object, "ChromeUtils") &&
isIdentifier(callee.property, "import") &&
node.arguments.length >= 2
) {
if (
node.arguments[1].type == "Literal" &&
node.arguments[1].raw == "null"
) {
context.report(
node,
"ChromeUtils.import should not be called with (..., null) to " +
"retrieve the JSM global object. Rely on explicit exports instead."
);
} else if (node.arguments[1].type == "ThisExpression") {
context.report({
node,
message:
"ChromeUtils.import should not be called with (..., this) to " +
"retrieve the JSM global object. Use destructuring instead.",
suggest: [
{
desc: "Use destructuring for imports.",
fix: fixer => {
let source = context.getSourceCode().getText(node);
let match = source.match(
/ChromeUtils.import\(\s*(".*\/(.*).jsm?")/m
);

return fixer.replaceText(
node,
`const { ${match[2]} } = ChromeUtils.import(${match[1]})`
);
},
},
],
});
}
}
},
};
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

var rule = require("../lib/rules/reject-chromeutils-import-params");
var RuleTester = require("eslint").RuleTester;

const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 8 } });

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

function invalidError() {
let message =
"ChromeUtils.import should not be called with (..., null) to " +
"retrieve the JSM global object. Rely on explicit exports instead.";
return [{ message, type: "CallExpression" }];
}

ruleTester.run("reject-chromeutils-import-params", rule, {
valid: ['ChromeUtils.import("resource://some/path/to/My.jsm")'],
invalid: [
{
code: 'ChromeUtils.import("resource://some/path/to/My.jsm", null)',
errors: invalidError(),
},
{
code: `
ChromeUtils.import(
"resource://some/path/to/My.jsm",
null
);`,
errors: invalidError(),
},
{
code: 'ChromeUtils.import("resource://some/path/to/My.jsm", this)',
errors: [
{
suggestions: [
{
desc: "Use destructuring for imports.",
output: `const { My } = ChromeUtils.import("resource://some/path/to/My.jsm")`,
},
],
},
],
},
{
code: 'ChromeUtils.import("resource://some/path/to/My.js", this)',
errors: [
{
suggestions: [
{
desc: "Use destructuring for imports.",
output: `const { My } = ChromeUtils.import("resource://some/path/to/My.js")`,
},
],
},
],
},
{
code: `
ChromeUtils.import(
"resource://some/path/to/My.jsm",
this
);`,
errors: [
{
suggestions: [
{
desc: "Use destructuring for imports.",
output: `
const { My } = ChromeUtils.import("resource://some/path/to/My.jsm");`,
},
],
},
],
},
],
});

0 comments on commit 67bf517

Please sign in to comment.