mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 12:50:09 +00:00
Bug 1330545 - [eslint] Handle importScripts in workers for determining global variables. r=mossop
MozReview-Commit-ID: 6NkcAcaNjur --HG-- extra : rebase_source : 2004e08b8e2e52b9ad329eb7604868ebe3bd60c6
This commit is contained in:
parent
6a9f5ff102
commit
72976b4efa
@ -65,15 +65,33 @@ const globalCache = new Map();
|
||||
* parents parameter which is a list of the parent nodes of the current node.
|
||||
* Each returns an array of globals found.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {String} filePath
|
||||
* The absolute path of the file being parsed.
|
||||
*/
|
||||
function GlobalsForNode(path) {
|
||||
this.path = path;
|
||||
this.root = helpers.getRootDir(path);
|
||||
function GlobalsForNode(filePath) {
|
||||
this.path = filePath;
|
||||
this.dirname = path.dirname(this.path)
|
||||
this.root = helpers.getRootDir(this.path);
|
||||
this.isWorker = helpers.getIsWorker(this.path);
|
||||
}
|
||||
|
||||
GlobalsForNode.prototype = {
|
||||
Program(node) {
|
||||
if (!this.isWorker) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{name: "importScripts", writable: false},
|
||||
// Only available to workers.
|
||||
{name: "FileReaderSync", writable: false},
|
||||
{name: "onmessage", writable: true},
|
||||
// Only available to chrome workers, but since we don't know which is which,
|
||||
// we make it available anyway.
|
||||
{name: "ctypes", writable: false}
|
||||
];
|
||||
},
|
||||
|
||||
BlockComment(node, parents) {
|
||||
let value = node.value.trim();
|
||||
let match = /^import-globals-from\s+(.+)$/.exec(value);
|
||||
@ -84,8 +102,7 @@ GlobalsForNode.prototype = {
|
||||
let filePath = match[1].trim();
|
||||
|
||||
if (!path.isAbsolute(filePath)) {
|
||||
let dirName = path.dirname(this.path);
|
||||
filePath = path.resolve(dirName, filePath);
|
||||
filePath = path.resolve(this.dirname, filePath);
|
||||
}
|
||||
|
||||
return module.exports.getGlobalsForFile(filePath);
|
||||
@ -93,8 +110,19 @@ GlobalsForNode.prototype = {
|
||||
|
||||
ExpressionStatement(node, parents) {
|
||||
let isGlobal = helpers.getIsGlobalScope(parents);
|
||||
let names = helpers.convertExpressionToGlobals(node, isGlobal, this.root);
|
||||
return names.map(name => { return { name, writable: true }});
|
||||
let globals = helpers.convertExpressionToGlobals(node, isGlobal, this.root);
|
||||
// Map these globals now, as getGlobalsForFile is pre-mapped.
|
||||
globals = globals.map(name => { return { name, writable: true }});
|
||||
|
||||
if (this.isWorker) {
|
||||
let workerDetails = helpers.convertWorkerExpressionToGlobals(node,
|
||||
isGlobal, this.root, this.dirname);
|
||||
globals = globals.concat(workerDetails.map(name => {
|
||||
return { name, writable: true };
|
||||
}));
|
||||
}
|
||||
|
||||
return globals;
|
||||
},
|
||||
};
|
||||
|
||||
@ -106,6 +134,12 @@ module.exports = {
|
||||
*
|
||||
* @param {String} path
|
||||
* The absolute path of the file to be parsed.
|
||||
* @return {Array}
|
||||
* An array of objects that contain details about the globals:
|
||||
* - {String} name
|
||||
* The name of the global.
|
||||
* - {Boolean} writable
|
||||
* If the global is writeable or not.
|
||||
*/
|
||||
getGlobalsForFile(path) {
|
||||
if (globalCache.has(path)) {
|
||||
@ -179,6 +213,9 @@ module.exports = {
|
||||
|
||||
for (let type of Object.keys(GlobalsForNode.prototype)) {
|
||||
parser[type] = function(node) {
|
||||
if (type === "Program") {
|
||||
globalScope = context.getScope();
|
||||
}
|
||||
let globals = handler[type](node, context.getAncestors());
|
||||
helpers.addGlobals(globals, globalScope);
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ var imports = [
|
||||
/^(?:Cu|Components\.utils)\.import\(".*\/((.*?)\.jsm?)"(?:, this)?\)/,
|
||||
];
|
||||
|
||||
var workerImportFilenameMatch = /(.*\/)*(.*?\.jsm?)/;
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Gets the abstract syntax tree (AST) of the JavaScript source code contained
|
||||
@ -168,8 +170,40 @@ module.exports = {
|
||||
* The root of the repository.
|
||||
*
|
||||
* @return {Array}
|
||||
* An array of variable names defined.
|
||||
* An array of global variable names defined.
|
||||
*/
|
||||
convertWorkerExpressionToGlobals: function(node, isGlobal, repository, dirname) {
|
||||
var getGlobalsForFile = require("./globals").getGlobalsForFile;
|
||||
|
||||
if (!modules) {
|
||||
modules = require(path.join(repository, "tools", "lint", "eslint", "modules.json"));
|
||||
}
|
||||
|
||||
let results = [];
|
||||
let expr = node.expression;
|
||||
|
||||
if (node.expression.type === "CallExpression" &&
|
||||
expr.callee &&
|
||||
expr.callee.type === "Identifier" &&
|
||||
expr.callee.name === "importScripts") {
|
||||
for (var arg of expr.arguments) {
|
||||
var match = arg.value.match(workerImportFilenameMatch);
|
||||
if (match) {
|
||||
if (!match[1]) {
|
||||
let filePath = path.resolve(dirname, match[2]);
|
||||
if (fs.existsSync(filePath)) {
|
||||
let additionalGlobals = getGlobalsForFile(filePath);
|
||||
results = results.concat(additionalGlobals);
|
||||
}
|
||||
} else if (match[2] in modules) {
|
||||
results.push(modules[match[2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
||||
convertExpressionToGlobals: function(node, isGlobal, repository) {
|
||||
if (!modules) {
|
||||
modules = require(path.join(repository, "tools", "lint", "eslint", "modules.json"));
|
||||
@ -460,6 +494,12 @@ module.exports = {
|
||||
return null;
|
||||
},
|
||||
|
||||
getIsWorker: function(filePath) {
|
||||
let filename = path.basename(this.cleanUpPath(filePath)).toLowerCase();
|
||||
|
||||
return filename.includes("worker");
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the root directory of the repository by walking up directories until
|
||||
* a .eslintignore file is found.
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eslint-plugin-mozilla",
|
||||
"version": "0.2.16",
|
||||
"version": "0.2.17",
|
||||
"description": "A collection of rules that help enforce JavaScript coding standard in the Mozilla project.",
|
||||
"keywords": [
|
||||
"eslint",
|
||||
|
@ -70,6 +70,7 @@
|
||||
"EventUtils.js": ["disableNonTestMouseEvents", "sendMouseEvent", "sendChar", "sendString", "sendKey", "synthesizeMouse", "synthesizeTouch", "synthesizeMouseAtPoint", "synthesizeTouchAtPoint", "synthesizeMouseAtCenter", "synthesizeTouchAtCenter", "synthesizeWheel", "synthesizeKey", "synthesizeMouseExpectEvent", "synthesizeKeyExpectEvent", "synthesizeText", "synthesizeComposition", "synthesizeQuerySelectedText"],
|
||||
"Extension.jsm": ["Extension", "ExtensionData"],
|
||||
"ExtensionAPI.jsm": ["ExtensionAPI", "ExtensionAPIs"],
|
||||
"ExtensionsUI.jsm": ["ExtensionsUI"],
|
||||
"extension-storage.js": ["ExtensionStorageEngine", "EncryptionRemoteTransformer", "KeyRingEncryptionRemoteTransformer"],
|
||||
"ExtensionXPCShellUtils.jsm": ["ExtensionTestUtils"],
|
||||
"fakeservices.js": ["FakeCryptoService", "FakeFilesystemService", "FakeGUIDService", "fakeSHA256HMAC"],
|
||||
@ -110,6 +111,7 @@
|
||||
"import_sub_module.jsm": ["SUBMODULE_IMPORTED", "test_obj"],
|
||||
"InlineSpellChecker.jsm": ["InlineSpellChecker", "SpellCheckHelper"],
|
||||
"JNI.jsm": ["JNI", "android_log"],
|
||||
"JSDOMParser.js": ["JSDOMParser"],
|
||||
"Jsbeautify.jsm": ["jsBeautify"],
|
||||
"jsdebugger.jsm": ["addDebuggerToGlobal"],
|
||||
"json2.js": ["JSON"],
|
||||
@ -149,7 +151,7 @@
|
||||
"offlineAppCache.jsm": ["OfflineAppCacheHelper"],
|
||||
"OrientationChangeHandler.jsm": [],
|
||||
"os.js": ["listDirectory", "getFileForPath", "abspath", "getPlatform"],
|
||||
"osfile.jsm": ["OS"],
|
||||
"osfile.jsm": ["OS", "require"],
|
||||
"osfile_async_front.jsm": ["OS"],
|
||||
"osfile_native.jsm": ["read"],
|
||||
"osfile_shared_allthreads.jsm": ["LOG", "clone", "Config", "Constants", "Type", "HollowStructure", "OSError", "Library", "declareFFI", "declareLazy", "declareLazyFFI", "normalizeBufferArgs", "projectValue", "isArrayBuffer", "isTypedArray", "defineLazyGetter", "OS"],
|
||||
@ -176,6 +178,7 @@
|
||||
"PromiseWorker.jsm": ["BasePromiseWorker"],
|
||||
"PushCrypto.jsm": ["PushCrypto", "concatArray"],
|
||||
"quit.js": ["goQuitApplication"],
|
||||
"Readability.js": ["Readability"],
|
||||
"record.js": ["WBORecord", "RecordManager", "CryptoWrapper", "CollectionKeyManager", "Collection"],
|
||||
"recursive_importA.jsm": ["foo", "bar"],
|
||||
"recursive_importB.jsm": ["baz", "qux"],
|
||||
@ -187,6 +190,7 @@
|
||||
"responsivedesign.jsm": ["ResponsiveUIManager"],
|
||||
"rest.js": ["RESTRequest", "RESTResponse", "TokenAuthenticatedRESTRequest", "SyncStorageRequest"],
|
||||
"rotaryengine.js": ["RotaryEngine", "RotaryRecord", "RotaryStore", "RotaryTracker"],
|
||||
"require.js": ["require"],
|
||||
"RTCStatsReport.jsm": ["convertToRTCStatsReport"],
|
||||
"scratchpad-manager.jsm": ["ScratchpadManager"],
|
||||
"server.js": ["MarionetteServer"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user