зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1773740 - Part 3: Cover js files including ChromeUtils r=Standard8
Differential Revision: https://phabricator.services.mozilla.com/D148938
This commit is contained in:
Родитель
e984382b9a
Коммит
39d7ee6f91
|
@ -5,6 +5,17 @@ Prefer ``.isInstance()`` in chrome scripts over the standard ``instanceof``
|
|||
operator for DOM interfaces, since the latter will return false when the object
|
||||
is created from a different context.
|
||||
|
||||
These files are covered:
|
||||
|
||||
- ``*.sys.mjs``
|
||||
- ``*.jsm``
|
||||
- ``*.jsm.js``
|
||||
- ``*.js`` with a heuristic
|
||||
|
||||
Since there is no straightforward way to detect chrome scripts, currently the
|
||||
linter assumes that any script including ``ChromeUtils`` is chrome privileged.
|
||||
This of course may not be sufficient and is open for change.
|
||||
|
||||
Examples of incorrect code for this rule:
|
||||
-----------------------------------------
|
||||
|
||||
|
|
|
@ -55,10 +55,6 @@ module.exports = {
|
|||
"mozilla/reject-global-this": "error",
|
||||
"mozilla/reject-globalThis-modification": "error",
|
||||
"mozilla/reject-top-level-await": "error",
|
||||
// Bug 1703953: We don't have a good way to check a file runs in a
|
||||
// privilieged context. Apply this for these files as we know those are
|
||||
// privilieged, and then include more directories elsewhere.
|
||||
"mozilla/use-isInstance": "error",
|
||||
// TODO: Bug 1575506 turn `builtinGlobals` on here.
|
||||
// We can enable builtinGlobals for jsms due to their scopes.
|
||||
"no-redeclare": ["error", { builtinGlobals: false }],
|
||||
|
@ -178,6 +174,7 @@ module.exports = {
|
|||
"mozilla/use-chromeutils-import": "error",
|
||||
"mozilla/use-default-preference-values": "error",
|
||||
"mozilla/use-includes-instead-of-indexOf": "error",
|
||||
"mozilla/use-isInstance": "error",
|
||||
"mozilla/use-ownerGlobal": "error",
|
||||
"mozilla/use-returnValue": "error",
|
||||
"mozilla/use-services": "error",
|
||||
|
|
|
@ -74,6 +74,24 @@ function pointsToDOMInterface(currentScope, node) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("eslint").Rule.RuleContext} context
|
||||
*/
|
||||
function isChromeContext(context) {
|
||||
const filename = context.getFilename();
|
||||
const isChromeFileName =
|
||||
filename.endsWith(".sys.mjs") ||
|
||||
filename.endsWith(".jsm") ||
|
||||
filename.endsWith(".jsm.js");
|
||||
if (isChromeFileName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Treat scripts using ChromeUtils as chrome scripts, but not SpecialPowers.ChromeUtils
|
||||
const source = context.getSourceCode().text;
|
||||
return !!source.match(/(^|\s)ChromeUtils/);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
docs: {
|
||||
|
@ -88,6 +106,10 @@ module.exports = {
|
|||
* @param {import("eslint").Rule.RuleContext} context
|
||||
*/
|
||||
create(context) {
|
||||
if (!isChromeContext(context)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
BinaryExpression(node) {
|
||||
const { operator, right } = node;
|
||||
|
|
|
@ -34,6 +34,19 @@ const env = { browser: true };
|
|||
function mockChromeScript(code) {
|
||||
return {
|
||||
code,
|
||||
filename: "foo.sys.mjs",
|
||||
env,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A test case boilerplate simulating content script.
|
||||
* @param {string} code
|
||||
*/
|
||||
function mockContentScript(code) {
|
||||
return {
|
||||
code,
|
||||
filename: "foo.js",
|
||||
env,
|
||||
};
|
||||
}
|
||||
|
@ -54,6 +67,11 @@ ruleTester.run("use-isInstance", rule, {
|
|||
mockChromeScript("var File;file instanceof File;"),
|
||||
mockChromeScript("foo instanceof RandomGlobalThing;"),
|
||||
mockChromeScript("foo instanceof lazy.RandomGlobalThing;"),
|
||||
mockContentScript("node instanceof Node;"),
|
||||
mockContentScript("file instanceof File;"),
|
||||
mockContentScript(
|
||||
"SpecialPowers.ChromeUtils.import(''); file instanceof File;"
|
||||
),
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
|
@ -61,32 +79,52 @@ ruleTester.run("use-isInstance", rule, {
|
|||
output: "Node.isInstance(node)",
|
||||
env,
|
||||
errors,
|
||||
filename: "foo.sys.mjs",
|
||||
},
|
||||
{
|
||||
code: "text instanceof win.Text",
|
||||
output: "win.Text.isInstance(text)",
|
||||
errors,
|
||||
filename: "foo.sys.mjs",
|
||||
},
|
||||
{
|
||||
code: "target instanceof this.contentWindow.HTMLAudioElement",
|
||||
output: "this.contentWindow.HTMLAudioElement.isInstance(target)",
|
||||
errors,
|
||||
filename: "foo.sys.mjs",
|
||||
},
|
||||
{
|
||||
code: "target instanceof File",
|
||||
output: "File.isInstance(target)",
|
||||
env,
|
||||
errors,
|
||||
filename: "foo.sys.mjs",
|
||||
},
|
||||
{
|
||||
code: "target instanceof win.File",
|
||||
output: "win.File.isInstance(target)",
|
||||
errors,
|
||||
filename: "foo.sys.mjs",
|
||||
},
|
||||
{
|
||||
code: "window.arguments[0] instanceof window.XULElement",
|
||||
output: "window.XULElement.isInstance(window.arguments[0])",
|
||||
errors,
|
||||
filename: "foo.sys.mjs",
|
||||
},
|
||||
{
|
||||
code: "ChromeUtils.import(''); node instanceof Node",
|
||||
output: "ChromeUtils.import(''); Node.isInstance(node)",
|
||||
env,
|
||||
errors,
|
||||
filename: "foo.js",
|
||||
},
|
||||
{
|
||||
code: "ChromeUtils.import(''); file instanceof File",
|
||||
output: "ChromeUtils.import(''); File.isInstance(file)",
|
||||
env,
|
||||
errors,
|
||||
filename: "foo.js",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче