mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1795880 - Add an ESLint rule to enforce using static imports where possible. r=arai,geckoview-reviewers,m_kato
Differential Revision: https://phabricator.services.mozilla.com/D160131
This commit is contained in:
parent
b1de2a15c2
commit
9613c19f16
@ -11,9 +11,7 @@ const RECENT_TABS_SYNC = "services.sync.lastTabFetch";
|
||||
const SHOULD_NOTIFY_FOR_TABS = "browser.tabs.firefox-view.notify-for-tabs";
|
||||
const lazy = {};
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
);
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
|
||||
|
@ -7,9 +7,7 @@
|
||||
* diverse inputs which drive the Firefox View synced tabs setup flow
|
||||
*/
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
);
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -2,9 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
);
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -2,9 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
const { SearchOneOffs } = ChromeUtils.importESModule(
|
||||
"resource:///modules/SearchOneOffs.sys.mjs"
|
||||
);
|
||||
import { SearchOneOffs } from "resource:///modules/SearchOneOffs.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -3,9 +3,7 @@
|
||||
* 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/. */
|
||||
|
||||
var { AppConstants } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/AppConstants.sys.mjs"
|
||||
);
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
|
||||
export async function runBackgroundTask(commandLine) {
|
||||
if (AppConstants.platform !== "win") {
|
||||
|
@ -2,9 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
var { WindowsRegistry: Registry } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/WindowsRegistry.sys.mjs"
|
||||
);
|
||||
import { WindowsRegistry as Registry } from "resource://gre/modules/WindowsRegistry.sys.mjs";
|
||||
|
||||
export var Windows8WindowFrameColor = {
|
||||
_windowFrameColor: null,
|
||||
|
@ -14,9 +14,8 @@ const ITEM_FLASH_DURATION = 300; // ms
|
||||
|
||||
import { require } from "resource://devtools/shared/loader/Loader.sys.mjs";
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
);
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const EventEmitter = require("resource://devtools/shared/event-emitter.js");
|
||||
const DevToolsUtils = require("resource://devtools/shared/DevToolsUtils.js");
|
||||
const {
|
||||
|
@ -72,6 +72,7 @@ The plugin implements the following rules:
|
||||
eslint-plugin-mozilla/use-ownerGlobal
|
||||
eslint-plugin-mozilla/use-returnValue
|
||||
eslint-plugin-mozilla/use-services
|
||||
eslint-plugin-mozilla/use-static-import
|
||||
eslint-plugin-mozilla/valid-ci-uses
|
||||
eslint-plugin-mozilla/valid-lazy
|
||||
eslint-plugin-mozilla/valid-services
|
||||
|
@ -0,0 +1,21 @@
|
||||
use-static-import
|
||||
=================
|
||||
|
||||
Requires the use of static imports in system ES module files (``.sys.mjs``)
|
||||
where possible.
|
||||
|
||||
Examples of incorrect code for this rule:
|
||||
-----------------------------------------
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs");
|
||||
const { XPCOMUtils: foo } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs");
|
||||
|
||||
Examples of correct code for this rule:
|
||||
---------------------------------------
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
import { XPCOMUtils as foo } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
@ -18,9 +18,7 @@
|
||||
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const { AppConstants } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/AppConstants.sys.mjs"
|
||||
);
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -4,9 +4,7 @@
|
||||
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
|
||||
const { clearTimeout, setTimeout } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/Timer.sys.mjs"
|
||||
);
|
||||
import { clearTimeout, setTimeout } from "resource://gre/modules/Timer.sys.mjs";
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
export var PushServiceWebSocket;
|
||||
|
@ -7,9 +7,7 @@ import { PushRecord } from "resource://gre/modules/PushRecord.sys.mjs";
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||
const { clearTimeout, setTimeout } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/Timer.sys.mjs"
|
||||
);
|
||||
import { clearTimeout, setTimeout } from "resource://gre/modules/Timer.sys.mjs";
|
||||
|
||||
import { PushCrypto } from "resource://gre/modules/PushCrypto.sys.mjs";
|
||||
|
||||
|
@ -2,9 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
);
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -4,9 +4,7 @@
|
||||
* 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/. */
|
||||
|
||||
const { AppConstants } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/AppConstants.sys.mjs"
|
||||
);
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
|
||||
let global = Cu.getGlobalForObject({});
|
||||
|
||||
|
@ -5,9 +5,7 @@
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
import { Log } from "resource://gre/modules/Log.sys.mjs";
|
||||
|
||||
const { clearTimeout, setTimeout } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/Timer.sys.mjs"
|
||||
);
|
||||
import { clearTimeout, setTimeout } from "resource://gre/modules/Timer.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -3,9 +3,7 @@
|
||||
* 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/. */
|
||||
|
||||
const { setTimeout } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/Timer.sys.mjs"
|
||||
);
|
||||
import { setTimeout } from "resource://gre/modules/Timer.sys.mjs";
|
||||
|
||||
export function runBackgroundTask(commandLine) {
|
||||
let delay = 10;
|
||||
|
@ -4,9 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
);
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
|
@ -2,9 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
);
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
let lazy = {};
|
||||
|
||||
|
@ -11,9 +11,7 @@ import { E10SUtils } from "resource://gre/modules/E10SUtils.sys.mjs";
|
||||
const { FeatureGate } = ChromeUtils.import(
|
||||
"resource://featuregates/FeatureGate.jsm"
|
||||
);
|
||||
const { PlacesDBUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/PlacesDBUtils.sys.mjs"
|
||||
);
|
||||
import { PlacesDBUtils } from "resource://gre/modules/PlacesDBUtils.sys.mjs";
|
||||
|
||||
// We use a list of prefs for display to make sure we only show prefs that
|
||||
// are useful for support and won't compromise the user's privacy. Note that
|
||||
|
@ -60,6 +60,12 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["**/*.sys.mjs"],
|
||||
rules: {
|
||||
"mozilla/use-static-import": "error",
|
||||
},
|
||||
},
|
||||
{
|
||||
excludedFiles: ["**/*.sys.mjs"],
|
||||
files: ["**/*.mjs"],
|
||||
@ -71,6 +77,7 @@ module.exports = {
|
||||
{
|
||||
files: ["**/*.mjs"],
|
||||
rules: {
|
||||
"mozilla/use-static-import": "error",
|
||||
// This rule defaults to not allowing "use strict" in module files since
|
||||
// they are always loaded in strict mode.
|
||||
strict: "error",
|
||||
|
@ -554,6 +554,21 @@ module.exports = {
|
||||
return true;
|
||||
},
|
||||
|
||||
isTopLevel(ancestors) {
|
||||
for (let parent of ancestors) {
|
||||
switch (parent.type) {
|
||||
case "ArrowFunctionExpression":
|
||||
case "FunctionDeclaration":
|
||||
case "FunctionExpression":
|
||||
case "PropertyDefinition":
|
||||
case "StaticBlock":
|
||||
case "BlockStatement":
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether `this` expression points the global this.
|
||||
*
|
||||
|
@ -85,6 +85,7 @@ module.exports = {
|
||||
"use-isInstance": require("./rules/use-isInstance"),
|
||||
"use-returnValue": require("../lib/rules/use-returnValue"),
|
||||
"use-services": require("../lib/rules/use-services"),
|
||||
"use-static-import": require("../lib/rules/use-static-import"),
|
||||
"valid-ci-uses": require("../lib/rules/valid-ci-uses"),
|
||||
"valid-lazy": require("../lib/rules/valid-lazy"),
|
||||
"valid-services": require("../lib/rules/valid-services"),
|
||||
|
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @fileoverview Require use of static imports where possible.
|
||||
*
|
||||
* 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 && node.type === "Identifier" && node.name === id;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
docs: {
|
||||
url:
|
||||
"https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/use-static-import.html",
|
||||
},
|
||||
fixable: "code",
|
||||
messages: {
|
||||
useStaticImport:
|
||||
"Please use static import instead of ChromeUtils.importESModule",
|
||||
},
|
||||
type: "suggestion",
|
||||
},
|
||||
|
||||
create(context) {
|
||||
return {
|
||||
VariableDeclarator(node) {
|
||||
if (
|
||||
node.init?.type != "CallExpression" ||
|
||||
node.init?.callee?.type != "MemberExpression" ||
|
||||
!context.getFilename().endsWith(".sys.mjs") ||
|
||||
!helpers.isTopLevel(context.getAncestors())
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let callee = node.init.callee;
|
||||
|
||||
if (
|
||||
isIdentifier(callee.object, "ChromeUtils") &&
|
||||
isIdentifier(callee.property, "importESModule") &&
|
||||
callee.parent.arguments.length == 1
|
||||
) {
|
||||
let sourceCode = context.getSourceCode();
|
||||
let importItemSource;
|
||||
if (node.id.type != "ObjectPattern") {
|
||||
importItemSource = sourceCode.getText(node.id);
|
||||
} else {
|
||||
importItemSource = "{ ";
|
||||
let initial = true;
|
||||
for (let property of node.id.properties) {
|
||||
if (!initial) {
|
||||
importItemSource += ", ";
|
||||
}
|
||||
initial = false;
|
||||
if (property.key.name == property.value.name) {
|
||||
importItemSource += property.key.name;
|
||||
} else {
|
||||
importItemSource += `${property.key.name} as ${property.value.name}`;
|
||||
}
|
||||
}
|
||||
importItemSource += " }";
|
||||
}
|
||||
|
||||
context.report({
|
||||
node: node.parent,
|
||||
messageId: "useStaticImport",
|
||||
fix(fixer) {
|
||||
return fixer.replaceText(
|
||||
node.parent,
|
||||
`import ${importItemSource} from ${sourceCode.getText(
|
||||
callee.parent.arguments[0]
|
||||
)}`
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
@ -0,0 +1,88 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
var rule = require("../lib/rules/use-static-import");
|
||||
var RuleTester = require("eslint").RuleTester;
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parserOptions: { ecmaVersion: 13, sourceType: "module" },
|
||||
});
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Tests
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
function callError() {
|
||||
return [{ messageId: "useStaticImport", type: "VariableDeclaration" }];
|
||||
}
|
||||
|
||||
ruleTester.run("use-static-import", rule, {
|
||||
valid: [
|
||||
{
|
||||
// Already converted, no issues.
|
||||
code:
|
||||
'import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";',
|
||||
filename: "test.sys.mjs",
|
||||
},
|
||||
{
|
||||
// Inside an if statement.
|
||||
code:
|
||||
'if (foo) { const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs") }',
|
||||
filename: "test.sys.mjs",
|
||||
},
|
||||
{
|
||||
// Inside a function.
|
||||
code:
|
||||
'function foo() { const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs") }',
|
||||
filename: "test.sys.mjs",
|
||||
},
|
||||
{
|
||||
// importESModule with two args cannot be converted.
|
||||
code:
|
||||
'const { f } = ChromeUtils.importESModule("some/module.sys.mjs", { loadInDevToolsLoader : true });',
|
||||
filename: "test.sys.mjs",
|
||||
},
|
||||
{
|
||||
// A non-system file attempting to import a system file should not be
|
||||
// converted.
|
||||
code:
|
||||
'const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs")',
|
||||
filename: "test.mjs",
|
||||
},
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
// Simple import in system module should be converted.
|
||||
code:
|
||||
'const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs")',
|
||||
errors: callError(),
|
||||
filename: "test.sys.mjs",
|
||||
output:
|
||||
'import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"',
|
||||
},
|
||||
{
|
||||
// Should handle rewritten variables as well.
|
||||
code:
|
||||
'const { XPCOMUtils: foo } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs")',
|
||||
errors: callError(),
|
||||
filename: "test.sys.mjs",
|
||||
output:
|
||||
'import { XPCOMUtils as foo } from "resource://gre/modules/XPCOMUtils.sys.mjs"',
|
||||
},
|
||||
{
|
||||
// Should handle multiple variables.
|
||||
code:
|
||||
'const { foo, XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs")',
|
||||
errors: callError(),
|
||||
filename: "test.sys.mjs",
|
||||
output:
|
||||
'import { foo, XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"',
|
||||
},
|
||||
],
|
||||
});
|
Loading…
Reference in New Issue
Block a user