forked from mirrors/gecko-dev
Bug 1561435 - Format tools/, a=automatic-formatting
# ignore-this-changeset Differential Revision: https://phabricator.services.mozilla.com/D35940 --HG-- extra : source : d214f0c82813e5a8d3987debc490a2c11f1308ff
This commit is contained in:
parent
336c4fb8a4
commit
5c7cdbd4ba
88 changed files with 2499 additions and 1910 deletions
|
|
@ -45,7 +45,6 @@ module.exports = {
|
||||||
"overrides": [{
|
"overrides": [{
|
||||||
"files": [
|
"files": [
|
||||||
"devtools/**",
|
"devtools/**",
|
||||||
"tools/**",
|
|
||||||
"uriloader/**",
|
"uriloader/**",
|
||||||
"view/**",
|
"view/**",
|
||||||
"widget/**",
|
"widget/**",
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@ toolkit/components/telemetry/datareporting-prefs.js
|
||||||
toolkit/components/telemetry/healthreport-prefs.js
|
toolkit/components/telemetry/healthreport-prefs.js
|
||||||
|
|
||||||
# Ignore all top-level directories for now.
|
# Ignore all top-level directories for now.
|
||||||
tools/**
|
|
||||||
uriloader/**
|
uriloader/**
|
||||||
view/**
|
view/**
|
||||||
widget/**
|
widget/**
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ["PerTestCoverageUtils"];
|
var EXPORTED_SYMBOLS = ["PerTestCoverageUtils"];
|
||||||
|
|
||||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
const env = Cc["@mozilla.org/process/environment;1"].getService(
|
||||||
|
Ci.nsIEnvironment
|
||||||
|
);
|
||||||
// This is the directory where gcov is emitting the gcda files.
|
// This is the directory where gcov is emitting the gcda files.
|
||||||
const gcovPrefixPath = env.get("GCOV_PREFIX");
|
const gcovPrefixPath = env.get("GCOV_PREFIX");
|
||||||
// This is the directory where codecoverage.py is expecting to see the gcda files.
|
// This is the directory where codecoverage.py is expecting to see the gcda files.
|
||||||
|
|
@ -20,7 +22,9 @@ const jsvmPrefixPath = env.get("JS_CODE_COVERAGE_OUTPUT_DIR");
|
||||||
// This is the directory where codecoverage.py is expecting to see the lcov files.
|
// This is the directory where codecoverage.py is expecting to see the lcov files.
|
||||||
const jsvmResultsPath = env.get("JSVM_RESULTS_DIR");
|
const jsvmResultsPath = env.get("JSVM_RESULTS_DIR");
|
||||||
|
|
||||||
const gcovPrefixDir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
const gcovPrefixDir = Cc["@mozilla.org/file/local;1"].createInstance(
|
||||||
|
Ci.nsIFile
|
||||||
|
);
|
||||||
if (gcovPrefixPath) {
|
if (gcovPrefixPath) {
|
||||||
gcovPrefixDir.initWithPath(gcovPrefixPath);
|
gcovPrefixDir.initWithPath(gcovPrefixPath);
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +34,9 @@ if (gcovResultsPath) {
|
||||||
gcovResultsDir.initWithPath(gcovResultsPath);
|
gcovResultsDir.initWithPath(gcovResultsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
const jsvmPrefixDir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
const jsvmPrefixDir = Cc["@mozilla.org/file/local;1"].createInstance(
|
||||||
|
Ci.nsIFile
|
||||||
|
);
|
||||||
if (jsvmPrefixPath) {
|
if (jsvmPrefixPath) {
|
||||||
jsvmPrefixDir.initWithPath(jsvmPrefixPath);
|
jsvmPrefixDir.initWithPath(jsvmPrefixPath);
|
||||||
}
|
}
|
||||||
|
|
@ -44,10 +50,12 @@ function awaitPromise(promise) {
|
||||||
let ret;
|
let ret;
|
||||||
let complete = false;
|
let complete = false;
|
||||||
let error = null;
|
let error = null;
|
||||||
promise.catch(e => error = e).then(v => {
|
promise
|
||||||
ret = v;
|
.catch(e => (error = e))
|
||||||
complete = true;
|
.then(v => {
|
||||||
});
|
ret = v;
|
||||||
|
complete = true;
|
||||||
|
});
|
||||||
Services.tm.spinEventLoopUntil(() => complete);
|
Services.tm.spinEventLoopUntil(() => complete);
|
||||||
if (error) {
|
if (error) {
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
|
|
@ -77,7 +85,9 @@ var PerTestCoverageUtils = class PerTestCoverageUtilsClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush the counters.
|
// Flush the counters.
|
||||||
let codeCoverageService = Cc["@mozilla.org/tools/code-coverage;1"].getService(Ci.nsICodeCoverage);
|
let codeCoverageService = Cc[
|
||||||
|
"@mozilla.org/tools/code-coverage;1"
|
||||||
|
].getService(Ci.nsICodeCoverage);
|
||||||
await codeCoverageService.flushCounters();
|
await codeCoverageService.flushCounters();
|
||||||
|
|
||||||
// Remove coverage files created by the flush, and those that might have been created between the end of a previous test and the beginning of the next one (e.g. some tests can create a new content process for every sub-test).
|
// Remove coverage files created by the flush, and those that might have been created between the end of a previous test and the beginning of the next one (e.g. some tests can create a new content process for every sub-test).
|
||||||
|
|
@ -100,7 +110,9 @@ var PerTestCoverageUtils = class PerTestCoverageUtilsClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush the counters.
|
// Flush the counters.
|
||||||
let codeCoverageService = Cc["@mozilla.org/tools/code-coverage;1"].getService(Ci.nsICodeCoverage);
|
let codeCoverageService = Cc[
|
||||||
|
"@mozilla.org/tools/code-coverage;1"
|
||||||
|
].getService(Ci.nsICodeCoverage);
|
||||||
await codeCoverageService.flushCounters();
|
await codeCoverageService.flushCounters();
|
||||||
|
|
||||||
// Move the coverage files in GCOV_RESULTS_DIR and JSVM_RESULTS_DIR, so that the execution from now to shutdown (or next test) is not counted.
|
// Move the coverage files in GCOV_RESULTS_DIR and JSVM_RESULTS_DIR, so that the execution from now to shutdown (or next test) is not counted.
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,21 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
var {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
var { AppConstants } = ChromeUtils.import(
|
||||||
var {OS, require} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
"resource://gre/modules/AppConstants.jsm"
|
||||||
|
);
|
||||||
|
var { OS, require } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
||||||
|
|
||||||
function getFiles() {
|
function getFiles() {
|
||||||
const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
const env = Cc["@mozilla.org/process/environment;1"].getService(
|
||||||
|
Ci.nsIEnvironment
|
||||||
|
);
|
||||||
// This is the directory where gcov is emitting the gcda files.
|
// This is the directory where gcov is emitting the gcda files.
|
||||||
const jsCoveragePath = env.get("JS_CODE_COVERAGE_OUTPUT_DIR");
|
const jsCoveragePath = env.get("JS_CODE_COVERAGE_OUTPUT_DIR");
|
||||||
|
|
||||||
const jsCoverageDir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
const jsCoverageDir = Cc["@mozilla.org/file/local;1"].createInstance(
|
||||||
|
Ci.nsIFile
|
||||||
|
);
|
||||||
jsCoverageDir.initWithPath(jsCoveragePath);
|
jsCoverageDir.initWithPath(jsCoveragePath);
|
||||||
|
|
||||||
let files = [];
|
let files = [];
|
||||||
|
|
@ -47,9 +53,9 @@ function parseRecords(files) {
|
||||||
|
|
||||||
let [hits, name] = recordContent.split(",");
|
let [hits, name] = recordContent.split(",");
|
||||||
currentSF.push({
|
currentSF.push({
|
||||||
"type": "FNDA",
|
type: "FNDA",
|
||||||
"hits": hits,
|
hits,
|
||||||
"name": name,
|
name,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -61,8 +67,8 @@ function parseRecords(files) {
|
||||||
|
|
||||||
let name = recordContent.split(",")[1];
|
let name = recordContent.split(",")[1];
|
||||||
currentSF.push({
|
currentSF.push({
|
||||||
"type": "FN",
|
type: "FN",
|
||||||
"name": name,
|
name,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,19 +29,41 @@ async function run_test() {
|
||||||
await codeCoverage.flushCounters();
|
await codeCoverage.flushCounters();
|
||||||
|
|
||||||
const first_flush_files = getFiles();
|
const first_flush_files = getFiles();
|
||||||
const first_flush_records = parseRecords(diffFiles(first_flush_files, files_orig));
|
const first_flush_records = parseRecords(
|
||||||
|
diffFiles(first_flush_files, files_orig)
|
||||||
|
);
|
||||||
|
|
||||||
Assert.ok(first_flush_records.has("test_basic.js"));
|
Assert.ok(first_flush_records.has("test_basic.js"));
|
||||||
let fnRecords = first_flush_records.get("test_basic.js").filter(record => record.type == "FN");
|
let fnRecords = first_flush_records
|
||||||
let fndaRecords = first_flush_records.get("test_basic.js").filter(record => record.type == "FNDA");
|
.get("test_basic.js")
|
||||||
|
.filter(record => record.type == "FN");
|
||||||
|
let fndaRecords = first_flush_records
|
||||||
|
.get("test_basic.js")
|
||||||
|
.filter(record => record.type == "FNDA");
|
||||||
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
||||||
Assert.ok(fnRecords.some(record => record.name == "run_test"));
|
Assert.ok(fnRecords.some(record => record.name == "run_test"));
|
||||||
Assert.ok(fnRecords.some(record => record.name == "test_code_coverage_func1"));
|
Assert.ok(
|
||||||
Assert.ok(fndaRecords.some(record => record.name == "run_test" && record.hits == 1));
|
fnRecords.some(record => record.name == "test_code_coverage_func1")
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "run_test" && record.hits != 1));
|
);
|
||||||
Assert.ok(fndaRecords.some(record => record.name == "test_code_coverage_func1" && record.hits == 1));
|
Assert.ok(
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "test_code_coverage_func1" && record.hits != 1));
|
fndaRecords.some(record => record.name == "run_test" && record.hits == 1)
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "test_code_coverage_func2"));
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(record => record.name == "run_test" && record.hits != 1)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func1" && record.hits == 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func1" && record.hits != 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(record => record.name == "test_code_coverage_func2")
|
||||||
|
);
|
||||||
|
|
||||||
test_code_coverage_func2();
|
test_code_coverage_func2();
|
||||||
|
|
||||||
|
|
@ -49,19 +71,45 @@ async function run_test() {
|
||||||
await codeCoverage.flushCounters();
|
await codeCoverage.flushCounters();
|
||||||
|
|
||||||
const second_flush_files = getFiles();
|
const second_flush_files = getFiles();
|
||||||
const second_flush_records = parseRecords(diffFiles(second_flush_files, first_flush_files));
|
const second_flush_records = parseRecords(
|
||||||
|
diffFiles(second_flush_files, first_flush_files)
|
||||||
|
);
|
||||||
|
|
||||||
Assert.ok(second_flush_records.has("test_basic.js"));
|
Assert.ok(second_flush_records.has("test_basic.js"));
|
||||||
fnRecords = second_flush_records.get("test_basic.js").filter(record => record.type == "FN");
|
fnRecords = second_flush_records
|
||||||
fndaRecords = second_flush_records.get("test_basic.js").filter(record => record.type == "FNDA");
|
.get("test_basic.js")
|
||||||
|
.filter(record => record.type == "FN");
|
||||||
|
fndaRecords = second_flush_records
|
||||||
|
.get("test_basic.js")
|
||||||
|
.filter(record => record.type == "FNDA");
|
||||||
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
||||||
Assert.ok(fnRecords.some(record => record.name == "run_test"));
|
Assert.ok(fnRecords.some(record => record.name == "run_test"));
|
||||||
Assert.ok(fnRecords.some(record => record.name == "test_code_coverage_func1"));
|
Assert.ok(
|
||||||
Assert.ok(fnRecords.some(record => record.name == "test_code_coverage_func2"));
|
fnRecords.some(record => record.name == "test_code_coverage_func1")
|
||||||
Assert.ok(fndaRecords.some(record => record.name == "test_code_coverage_func1" && record.hits == 0));
|
);
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "test_code_coverage_func1" && record.hits != 0));
|
Assert.ok(
|
||||||
Assert.ok(fndaRecords.some(record => record.name == "test_code_coverage_func2" && record.hits == 1));
|
fnRecords.some(record => record.name == "test_code_coverage_func2")
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "test_code_coverage_func2" && record.hits != 1));
|
);
|
||||||
|
Assert.ok(
|
||||||
|
fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func1" && record.hits == 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func1" && record.hits != 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func2" && record.hits == 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func2" && record.hits != 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
do_test_finished();
|
do_test_finished();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@ async function run_test() {
|
||||||
do_load_child_test_harness();
|
do_load_child_test_harness();
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
|
|
||||||
const codeCoverage = Cc["@mozilla.org/tools/code-coverage;1"].getService(Ci.nsICodeCoverage);
|
const codeCoverage = Cc["@mozilla.org/tools/code-coverage;1"].getService(
|
||||||
|
Ci.nsICodeCoverage
|
||||||
|
);
|
||||||
|
|
||||||
const files_orig = getFiles();
|
const files_orig = getFiles();
|
||||||
|
|
||||||
|
|
@ -19,44 +21,100 @@ async function run_test() {
|
||||||
await codeCoverage.flushCounters();
|
await codeCoverage.flushCounters();
|
||||||
|
|
||||||
const first_flush_files = getFiles();
|
const first_flush_files = getFiles();
|
||||||
const first_flush_records = parseRecords(diffFiles(first_flush_files, files_orig));
|
const first_flush_records = parseRecords(
|
||||||
|
diffFiles(first_flush_files, files_orig)
|
||||||
|
);
|
||||||
|
|
||||||
Assert.ok(first_flush_records.has("test_basic_child_and_parent.js"));
|
Assert.ok(first_flush_records.has("test_basic_child_and_parent.js"));
|
||||||
Assert.ok(!first_flush_records.has("support.js"));
|
Assert.ok(!first_flush_records.has("support.js"));
|
||||||
let fnRecords = first_flush_records.get("test_basic_child_and_parent.js").filter(record => record.type == "FN");
|
let fnRecords = first_flush_records
|
||||||
let fndaRecords = first_flush_records.get("test_basic_child_and_parent.js").filter(record => record.type == "FNDA");
|
.get("test_basic_child_and_parent.js")
|
||||||
|
.filter(record => record.type == "FN");
|
||||||
|
let fndaRecords = first_flush_records
|
||||||
|
.get("test_basic_child_and_parent.js")
|
||||||
|
.filter(record => record.type == "FNDA");
|
||||||
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
||||||
Assert.ok(fnRecords.some(record => record.name == "run_test"));
|
Assert.ok(fnRecords.some(record => record.name == "run_test"));
|
||||||
Assert.ok(fnRecords.some(record => record.name == "test_code_coverage_func1"));
|
Assert.ok(
|
||||||
Assert.ok(fndaRecords.some(record => record.name == "run_test" && record.hits == 1));
|
fnRecords.some(record => record.name == "test_code_coverage_func1")
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "run_test" && record.hits != 1));
|
);
|
||||||
Assert.ok(fndaRecords.some(record => record.name == "test_code_coverage_func1" && record.hits == 1));
|
Assert.ok(
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "test_code_coverage_func1" && record.hits != 1));
|
fndaRecords.some(record => record.name == "run_test" && record.hits == 1)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(record => record.name == "run_test" && record.hits != 1)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func1" && record.hits == 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func1" && record.hits != 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
sendCommand("load('support.js');", async function() {
|
sendCommand("load('support.js');", async function() {
|
||||||
await codeCoverage.flushCounters();
|
await codeCoverage.flushCounters();
|
||||||
|
|
||||||
const second_flush_files = getFiles();
|
const second_flush_files = getFiles();
|
||||||
const second_flush_records = parseRecords(diffFiles(second_flush_files, first_flush_files));
|
const second_flush_records = parseRecords(
|
||||||
|
diffFiles(second_flush_files, first_flush_files)
|
||||||
|
);
|
||||||
|
|
||||||
Assert.ok(second_flush_records.has("test_basic_child_and_parent.js"));
|
Assert.ok(second_flush_records.has("test_basic_child_and_parent.js"));
|
||||||
fnRecords = second_flush_records.get("test_basic_child_and_parent.js").filter(record => record.type == "FN");
|
fnRecords = second_flush_records
|
||||||
fndaRecords = second_flush_records.get("test_basic_child_and_parent.js").filter(record => record.type == "FNDA");
|
.get("test_basic_child_and_parent.js")
|
||||||
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
.filter(record => record.type == "FN");
|
||||||
Assert.ok(fnRecords.some(record => record.name == "run_test"));
|
fndaRecords = second_flush_records
|
||||||
Assert.ok(fnRecords.some(record => record.name == "test_code_coverage_func1"));
|
.get("test_basic_child_and_parent.js")
|
||||||
Assert.ok(fndaRecords.some(record => record.name == "test_code_coverage_func1" && record.hits == 0));
|
.filter(record => record.type == "FNDA");
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "test_code_coverage_func1" && record.hits != 0));
|
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
||||||
Assert.ok(second_flush_records.has("support.js"));
|
Assert.ok(fnRecords.some(record => record.name == "run_test"));
|
||||||
fnRecords = second_flush_records.get("support.js").filter(record => record.type == "FN");
|
Assert.ok(
|
||||||
fndaRecords = second_flush_records.get("support.js").filter(record => record.type == "FNDA");
|
fnRecords.some(record => record.name == "test_code_coverage_func1")
|
||||||
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
);
|
||||||
Assert.ok(fnRecords.some(record => record.name == "test_code_coverage_func2"));
|
Assert.ok(
|
||||||
Assert.ok(fndaRecords.some(record => record.name == "top-level" && record.hits == 1));
|
fndaRecords.some(
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "top-level" && record.hits != 1));
|
record => record.name == "test_code_coverage_func1" && record.hits == 0
|
||||||
Assert.ok(fndaRecords.some(record => record.name == "test_code_coverage_func2" && record.hits == 1));
|
)
|
||||||
Assert.ok(!fndaRecords.some(record => record.name == "test_code_coverage_func2" && record.hits != 1));
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func1" && record.hits != 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Assert.ok(second_flush_records.has("support.js"));
|
||||||
|
fnRecords = second_flush_records
|
||||||
|
.get("support.js")
|
||||||
|
.filter(record => record.type == "FN");
|
||||||
|
fndaRecords = second_flush_records
|
||||||
|
.get("support.js")
|
||||||
|
.filter(record => record.type == "FNDA");
|
||||||
|
Assert.ok(fnRecords.some(record => record.name == "top-level"));
|
||||||
|
Assert.ok(
|
||||||
|
fnRecords.some(record => record.name == "test_code_coverage_func2")
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
fndaRecords.some(record => record.name == "top-level" && record.hits == 1)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(
|
||||||
|
record => record.name == "top-level" && record.hits != 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func2" && record.hits == 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Assert.ok(
|
||||||
|
!fndaRecords.some(
|
||||||
|
record => record.name == "test_code_coverage_func2" && record.hits != 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
do_test_finished();
|
do_test_finished();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,64 +2,62 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"env": {
|
env: {
|
||||||
"browser": true,
|
browser: true,
|
||||||
"mozilla/browser-window": true,
|
"mozilla/browser-window": true,
|
||||||
"mozilla/simpletest": true,
|
"mozilla/simpletest": true,
|
||||||
// "node": true
|
// "node": true
|
||||||
},
|
},
|
||||||
|
|
||||||
// All globals made available in the test environment.
|
// All globals made available in the test environment.
|
||||||
"globals": {
|
globals: {
|
||||||
// `$` is defined in SimpleTest.js
|
// `$` is defined in SimpleTest.js
|
||||||
"$": false,
|
$: false,
|
||||||
"Assert": false,
|
Assert: false,
|
||||||
"BrowserTestUtils": false,
|
BrowserTestUtils: false,
|
||||||
"ContentTask": false,
|
ContentTask: false,
|
||||||
"ContentTaskUtils": false,
|
ContentTaskUtils: false,
|
||||||
"EventUtils": false,
|
EventUtils: false,
|
||||||
"PromiseDebugging": false,
|
PromiseDebugging: false,
|
||||||
"SpecialPowers": false,
|
SpecialPowers: false,
|
||||||
"TestUtils": false,
|
TestUtils: false,
|
||||||
"XPCNativeWrapper": false,
|
XPCNativeWrapper: false,
|
||||||
"XULDocument": false,
|
XULDocument: false,
|
||||||
"addLoadEvent": false,
|
addLoadEvent: false,
|
||||||
"add_task": false,
|
add_task: false,
|
||||||
"content": false,
|
content: false,
|
||||||
"executeSoon": false,
|
executeSoon: false,
|
||||||
"expectUncaughtException": false,
|
expectUncaughtException: false,
|
||||||
"export_assertions": false,
|
export_assertions: false,
|
||||||
"extractJarToTmp": false,
|
extractJarToTmp: false,
|
||||||
"finish": false,
|
finish: false,
|
||||||
"gTestPath": false,
|
gTestPath: false,
|
||||||
"getChromeDir": false,
|
getChromeDir: false,
|
||||||
"getJar": false,
|
getJar: false,
|
||||||
"getResolvedURI": false,
|
getResolvedURI: false,
|
||||||
"getRootDirectory": false,
|
getRootDirectory: false,
|
||||||
"getTestFilePath": false,
|
getTestFilePath: false,
|
||||||
"ignoreAllUncaughtExceptions": false,
|
ignoreAllUncaughtExceptions: false,
|
||||||
"info": false,
|
info: false,
|
||||||
"is": false,
|
is: false,
|
||||||
"isnot": false,
|
isnot: false,
|
||||||
"ok": false,
|
ok: false,
|
||||||
"privateNoteIntentionalCrash": false,
|
privateNoteIntentionalCrash: false,
|
||||||
"record": false,
|
record: false,
|
||||||
"registerCleanupFunction": false,
|
registerCleanupFunction: false,
|
||||||
"requestLongerTimeout": false,
|
requestLongerTimeout: false,
|
||||||
"setExpectedFailuresForSelfTest": false,
|
setExpectedFailuresForSelfTest: false,
|
||||||
"todo": false,
|
todo: false,
|
||||||
"todo_is": false,
|
todo_is: false,
|
||||||
"todo_isnot": false,
|
todo_isnot: false,
|
||||||
"waitForClipboard": false,
|
waitForClipboard: false,
|
||||||
"waitForExplicitFinish": false,
|
waitForExplicitFinish: false,
|
||||||
"waitForFocus": false,
|
waitForFocus: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
"plugins": [
|
plugins: ["mozilla"],
|
||||||
"mozilla",
|
|
||||||
],
|
|
||||||
|
|
||||||
"rules": {
|
rules: {
|
||||||
"mozilla/import-content-task-globals": "error",
|
"mozilla/import-content-task-globals": "error",
|
||||||
"mozilla/import-headjs-globals": "error",
|
"mozilla/import-headjs-globals": "error",
|
||||||
"mozilla/mark-test-function-used": "error",
|
"mozilla/mark-test-function-used": "error",
|
||||||
|
|
|
||||||
|
|
@ -2,31 +2,31 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"env": {
|
env: {
|
||||||
"browser": true,
|
browser: true,
|
||||||
"mozilla/browser-window": true,
|
"mozilla/browser-window": true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// All globals made available in the test environment.
|
// All globals made available in the test environment.
|
||||||
"globals": {
|
globals: {
|
||||||
// SpecialPowers is injected into the window object via SimpleTest.js
|
// SpecialPowers is injected into the window object via SimpleTest.js
|
||||||
"SpecialPowers": false,
|
SpecialPowers: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
"overrides": [{
|
overrides: [
|
||||||
"env": {
|
{
|
||||||
// Ideally we wouldn't be using the simpletest env here, but our uses of
|
env: {
|
||||||
// js files mean we pick up everything from the global scope, which could
|
// Ideally we wouldn't be using the simpletest env here, but our uses of
|
||||||
// be any one of a number of html files. So we just allow the basics...
|
// js files mean we pick up everything from the global scope, which could
|
||||||
"mozilla/simpletest": true,
|
// be any one of a number of html files. So we just allow the basics...
|
||||||
|
"mozilla/simpletest": true,
|
||||||
|
},
|
||||||
|
files: ["*.js"],
|
||||||
},
|
},
|
||||||
"files": ["*.js"],
|
|
||||||
}],
|
|
||||||
|
|
||||||
"plugins": [
|
|
||||||
"mozilla",
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
plugins: ["mozilla"],
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
"mozilla/import-content-task-globals": "error",
|
"mozilla/import-content-task-globals": "error",
|
||||||
"mozilla/import-headjs-globals": "error",
|
"mozilla/import-headjs-globals": "error",
|
||||||
|
|
|
||||||
|
|
@ -2,32 +2,32 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"env": {
|
env: {
|
||||||
"browser": true,
|
browser: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// All globals made available in the test environment.
|
// All globals made available in the test environment.
|
||||||
"globals": {
|
globals: {
|
||||||
// SpecialPowers is injected into the window object via SimpleTest.js
|
// SpecialPowers is injected into the window object via SimpleTest.js
|
||||||
"SpecialPowers": false,
|
SpecialPowers: false,
|
||||||
"XPCNativeWrapper": false,
|
XPCNativeWrapper: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
"overrides": [{
|
overrides: [
|
||||||
"env": {
|
{
|
||||||
// Ideally we wouldn't be using the simpletest env here, but our uses of
|
env: {
|
||||||
// js files mean we pick up everything from the global scope, which could
|
// Ideally we wouldn't be using the simpletest env here, but our uses of
|
||||||
// be any one of a number of html files. So we just allow the basics...
|
// js files mean we pick up everything from the global scope, which could
|
||||||
"mozilla/simpletest": true,
|
// be any one of a number of html files. So we just allow the basics...
|
||||||
|
"mozilla/simpletest": true,
|
||||||
|
},
|
||||||
|
files: ["*.js"],
|
||||||
},
|
},
|
||||||
"files": ["*.js"],
|
|
||||||
}],
|
|
||||||
|
|
||||||
"plugins": [
|
|
||||||
"mozilla",
|
|
||||||
],
|
],
|
||||||
|
|
||||||
"rules": {
|
plugins: ["mozilla"],
|
||||||
|
|
||||||
|
rules: {
|
||||||
"mozilla/import-content-task-globals": "error",
|
"mozilla/import-content-task-globals": "error",
|
||||||
"mozilla/import-headjs-globals": "error",
|
"mozilla/import-headjs-globals": "error",
|
||||||
"mozilla/mark-test-function-used": "error",
|
"mozilla/mark-test-function-used": "error",
|
||||||
|
|
|
||||||
|
|
@ -8,89 +8,88 @@
|
||||||
* https://eslint.org/docs/rules/
|
* https://eslint.org/docs/rules/
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"env": {
|
env: {
|
||||||
"browser": true,
|
browser: true,
|
||||||
"es6": true,
|
es6: true,
|
||||||
"mozilla/privileged": true,
|
"mozilla/privileged": true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"extends": [
|
extends: ["eslint:recommended", "plugin:prettier/recommended"],
|
||||||
"eslint:recommended",
|
|
||||||
"plugin:prettier/recommended",
|
|
||||||
],
|
|
||||||
|
|
||||||
"globals": {
|
globals: {
|
||||||
"Cc": false,
|
Cc: false,
|
||||||
// Specific to Firefox (Chrome code only).
|
// Specific to Firefox (Chrome code only).
|
||||||
"ChromeUtils": false,
|
ChromeUtils: false,
|
||||||
"Ci": false,
|
Ci: false,
|
||||||
"Components": false,
|
Components: false,
|
||||||
"Cr": false,
|
Cr: false,
|
||||||
"Cu": false,
|
Cu: false,
|
||||||
"Debugger": false,
|
Debugger: false,
|
||||||
"InstallTrigger": false,
|
InstallTrigger: false,
|
||||||
// Specific to Firefox
|
// Specific to Firefox
|
||||||
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/InternalError
|
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/InternalError
|
||||||
"InternalError": true,
|
InternalError: true,
|
||||||
"Intl": false,
|
Intl: false,
|
||||||
"SharedArrayBuffer": false,
|
SharedArrayBuffer: false,
|
||||||
"StopIteration": false,
|
StopIteration: false,
|
||||||
"dump": true,
|
dump: true,
|
||||||
// Override the "browser" env definition of "location" to allow writing as it
|
// Override the "browser" env definition of "location" to allow writing as it
|
||||||
// is a writeable property.
|
// is a writeable property.
|
||||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1509270#c1 for more information.
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1509270#c1 for more information.
|
||||||
"location": true,
|
location: true,
|
||||||
"openDialog": false,
|
openDialog: false,
|
||||||
"saveStack": false,
|
saveStack: false,
|
||||||
"sizeToContent": false,
|
sizeToContent: false,
|
||||||
// Specific to Firefox
|
// Specific to Firefox
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/uneval
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/uneval
|
||||||
"uneval": false,
|
uneval: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
"overrides": [{
|
overrides: [
|
||||||
// Turn off use-services for xml files. XBL bindings are going away, and
|
{
|
||||||
// working out the valid globals for those is difficult.
|
// Turn off use-services for xml files. XBL bindings are going away, and
|
||||||
"files": "**/*.xml",
|
// working out the valid globals for those is difficult.
|
||||||
"rules": {
|
files: "**/*.xml",
|
||||||
"mozilla/use-services": "off",
|
rules: {
|
||||||
|
"mozilla/use-services": "off",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}, {
|
{
|
||||||
// We don't have the general browser environment for jsm files, but we do
|
// We don't have the general browser environment for jsm files, but we do
|
||||||
// have our own special environments for them.
|
// have our own special environments for them.
|
||||||
"env": {
|
env: {
|
||||||
"browser": false,
|
browser: false,
|
||||||
"mozilla/jsm": true,
|
"mozilla/jsm": true,
|
||||||
|
},
|
||||||
|
files: "**/*.jsm",
|
||||||
|
rules: {
|
||||||
|
"mozilla/mark-exported-symbols-as-used": "error",
|
||||||
|
// JSM modules are far easier to check for no-unused-vars on a global scope,
|
||||||
|
// than our content files. Hence we turn that on here.
|
||||||
|
"no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
args: "none",
|
||||||
|
vars: "all",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"files": "**/*.jsm",
|
],
|
||||||
"rules": {
|
|
||||||
"mozilla/mark-exported-symbols-as-used": "error",
|
|
||||||
// JSM modules are far easier to check for no-unused-vars on a global scope,
|
|
||||||
// than our content files. Hence we turn that on here.
|
|
||||||
"no-unused-vars": ["error", {
|
|
||||||
"args": "none",
|
|
||||||
"vars": "all",
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
|
|
||||||
"parserOptions": {
|
parserOptions: {
|
||||||
"ecmaVersion": 9,
|
ecmaVersion: 9,
|
||||||
},
|
},
|
||||||
|
|
||||||
// When adding items to this file please check for effects on sub-directories.
|
// When adding items to this file please check for effects on sub-directories.
|
||||||
"plugins": [
|
plugins: ["html", "fetch-options", "no-unsanitized"],
|
||||||
"html",
|
|
||||||
"fetch-options",
|
|
||||||
"no-unsanitized",
|
|
||||||
],
|
|
||||||
|
|
||||||
// When adding items to this file please check for effects on all of toolkit
|
// When adding items to this file please check for effects on all of toolkit
|
||||||
// and browser
|
// and browser
|
||||||
"rules": {
|
rules: {
|
||||||
// Warn about cyclomatic complexity in functions.
|
// Warn about cyclomatic complexity in functions.
|
||||||
// XXX Get this down to 20?
|
// XXX Get this down to 20?
|
||||||
"complexity": ["error", 34],
|
complexity: ["error", 34],
|
||||||
|
|
||||||
// Functions must always return something or nothing
|
// Functions must always return something or nothing
|
||||||
"consistent-return": "error",
|
"consistent-return": "error",
|
||||||
|
|
@ -100,7 +99,7 @@ module.exports = {
|
||||||
"constructor-super": "off",
|
"constructor-super": "off",
|
||||||
|
|
||||||
// Require braces around blocks that start a new line
|
// Require braces around blocks that start a new line
|
||||||
"curly": ["error", "all"],
|
curly: ["error", "all"],
|
||||||
|
|
||||||
// Encourage the use of dot notation whenever possible.
|
// Encourage the use of dot notation whenever possible.
|
||||||
"dot-notation": "error",
|
"dot-notation": "error",
|
||||||
|
|
@ -164,7 +163,7 @@ module.exports = {
|
||||||
"no-else-return": "error",
|
"no-else-return": "error",
|
||||||
|
|
||||||
// No empty statements
|
// No empty statements
|
||||||
"no-empty": ["error", {"allowEmptyCatch": true}],
|
"no-empty": ["error", { allowEmptyCatch: true }],
|
||||||
|
|
||||||
// Disallow eval and setInteral/setTimeout with strings
|
// Disallow eval and setInteral/setTimeout with strings
|
||||||
"no-eval": "error",
|
"no-eval": "error",
|
||||||
|
|
@ -189,7 +188,7 @@ module.exports = {
|
||||||
// Disallow the use of the __iterator__ property
|
// Disallow the use of the __iterator__ property
|
||||||
"no-iterator": "error",
|
"no-iterator": "error",
|
||||||
|
|
||||||
// No labels
|
// No labels
|
||||||
"no-labels": "error",
|
"no-labels": "error",
|
||||||
|
|
||||||
// Disallow unnecessary nested blocks
|
// Disallow unnecessary nested blocks
|
||||||
|
|
@ -238,10 +237,13 @@ module.exports = {
|
||||||
"no-unsanitized/property": "error",
|
"no-unsanitized/property": "error",
|
||||||
|
|
||||||
// No declaring variables that are never used
|
// No declaring variables that are never used
|
||||||
"no-unused-vars": ["error", {
|
"no-unused-vars": [
|
||||||
"args": "none",
|
"error",
|
||||||
"vars": "local",
|
{
|
||||||
}],
|
args: "none",
|
||||||
|
vars: "local",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
// No using variables before defined
|
// No using variables before defined
|
||||||
// "no-use-before-define": ["error", "nofunc"],
|
// "no-use-before-define": ["error", "nofunc"],
|
||||||
|
|
@ -264,7 +266,7 @@ module.exports = {
|
||||||
"no-with": "error",
|
"no-with": "error",
|
||||||
|
|
||||||
// Require object-literal shorthand with ES6 method syntax
|
// Require object-literal shorthand with ES6 method syntax
|
||||||
"object-shorthand": ["error", "always", { "avoidQuotes": true }],
|
"object-shorthand": ["error", "always", { avoidQuotes: true }],
|
||||||
|
|
||||||
// XXX Bug 1487642 - decide if we want to enable this or not.
|
// XXX Bug 1487642 - decide if we want to enable this or not.
|
||||||
// Require generator functions to contain yield
|
// Require generator functions to contain yield
|
||||||
|
|
@ -274,7 +276,7 @@ module.exports = {
|
||||||
// To avoid bad interactions of the html plugin with the xml preprocessor in
|
// To avoid bad interactions of the html plugin with the xml preprocessor in
|
||||||
// eslint-plugin-mozilla, we turn off processing of the html plugin for .xml
|
// eslint-plugin-mozilla, we turn off processing of the html plugin for .xml
|
||||||
// files.
|
// files.
|
||||||
"settings": {
|
settings: {
|
||||||
"html/xml-extensions": [ ".xhtml" ],
|
"html/xml-extensions": [".xhtml"],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,80 +3,85 @@
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// All globals made available in the test environment.
|
// All globals made available in the test environment.
|
||||||
"globals": {
|
globals: {
|
||||||
"Assert": false,
|
Assert: false,
|
||||||
"PromiseDebugging": false,
|
PromiseDebugging: false,
|
||||||
"_TEST_FILE": false,
|
_TEST_FILE: false,
|
||||||
"add_task": false,
|
add_task: false,
|
||||||
"add_test": false,
|
add_test: false,
|
||||||
// Test-only function.
|
// Test-only function.
|
||||||
"allocationMarker": false,
|
allocationMarker: false,
|
||||||
"byteSize": false,
|
byteSize: false,
|
||||||
"deepEqual": false,
|
deepEqual: false,
|
||||||
"do_await_remote_message": false,
|
do_await_remote_message: false,
|
||||||
"do_check_instanceof": false,
|
do_check_instanceof: false,
|
||||||
"do_get_cwd": false,
|
do_get_cwd: false,
|
||||||
"do_get_file": false,
|
do_get_file: false,
|
||||||
"do_get_idle": false,
|
do_get_idle: false,
|
||||||
"do_get_profile": false,
|
do_get_profile: false,
|
||||||
"do_get_tempdir": false,
|
do_get_tempdir: false,
|
||||||
"do_load_child_test_harness": false,
|
do_load_child_test_harness: false,
|
||||||
"do_load_manifest": false,
|
do_load_manifest: false,
|
||||||
"do_load_module": false,
|
do_load_module: false,
|
||||||
"do_note_exception": false,
|
do_note_exception: false,
|
||||||
"do_parse_document": false,
|
do_parse_document: false,
|
||||||
"do_report_unexpected_exception": false,
|
do_report_unexpected_exception: false,
|
||||||
"do_send_remote_message": false,
|
do_send_remote_message: false,
|
||||||
"do_test_finished": false,
|
do_test_finished: false,
|
||||||
"do_test_pending": false,
|
do_test_pending: false,
|
||||||
"do_throw": false,
|
do_throw: false,
|
||||||
"do_timeout": false,
|
do_timeout: false,
|
||||||
"equal": false,
|
equal: false,
|
||||||
"executeSoon": false,
|
executeSoon: false,
|
||||||
"gc": false,
|
gc: false,
|
||||||
// XPCShell specific function, see XPCShellEnvironment.cpp
|
// XPCShell specific function, see XPCShellEnvironment.cpp
|
||||||
"gczeal": false,
|
gczeal: false,
|
||||||
"greater": false,
|
greater: false,
|
||||||
"greaterOrEqual": false,
|
greaterOrEqual: false,
|
||||||
"info": false,
|
info: false,
|
||||||
"less": false,
|
less: false,
|
||||||
"lessOrEqual": false,
|
lessOrEqual: false,
|
||||||
"load": false,
|
load: false,
|
||||||
"mozinfo": false,
|
mozinfo: false,
|
||||||
"notDeepEqual": false,
|
notDeepEqual: false,
|
||||||
"notEqual": false,
|
notEqual: false,
|
||||||
"notStrictEqual": false,
|
notStrictEqual: false,
|
||||||
"ok": false,
|
ok: false,
|
||||||
"registerCleanupFunction": false,
|
registerCleanupFunction: false,
|
||||||
"run_next_test": false,
|
run_next_test: false,
|
||||||
"run_test": false,
|
run_test: false,
|
||||||
"run_test_in_child": false,
|
run_test_in_child: false,
|
||||||
"runningInParent": false,
|
runningInParent: false,
|
||||||
// Defined in XPCShellImpl.
|
// Defined in XPCShellImpl.
|
||||||
"sendCommand": false,
|
sendCommand: false,
|
||||||
"strictEqual": false,
|
strictEqual: false,
|
||||||
"throws": false,
|
throws: false,
|
||||||
"todo": false,
|
todo: false,
|
||||||
"todo_check_false": false,
|
todo_check_false: false,
|
||||||
"todo_check_true": false,
|
todo_check_true: false,
|
||||||
// Firefox specific function.
|
// Firefox specific function.
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/uneval
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/uneval
|
||||||
"uneval": false,
|
uneval: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
"overrides": [{
|
overrides: [
|
||||||
// If it is a head file, we turn off global unused variable checks, as it
|
{
|
||||||
// would require searching the other test files to know if they are used or not.
|
// If it is a head file, we turn off global unused variable checks, as it
|
||||||
// This would be expensive and slow, and it isn't worth it for head files.
|
// would require searching the other test files to know if they are used or not.
|
||||||
// We could get developers to declare as exported, but that doesn't seem worth it.
|
// This would be expensive and slow, and it isn't worth it for head files.
|
||||||
"files": "head*.js",
|
// We could get developers to declare as exported, but that doesn't seem worth it.
|
||||||
"rules": {
|
files: "head*.js",
|
||||||
"no-unused-vars": ["error", {
|
rules: {
|
||||||
"args": "none",
|
"no-unused-vars": [
|
||||||
"vars": "local",
|
"error",
|
||||||
}],
|
{
|
||||||
|
args: "none",
|
||||||
|
vars: "local",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}],
|
],
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
"mozilla/import-headjs-globals": "error",
|
"mozilla/import-headjs-globals": "error",
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ const extraDefinitions = [
|
||||||
// Via Components.utils, defineModuleGetter, defineLazyModuleGetters or
|
// Via Components.utils, defineModuleGetter, defineLazyModuleGetters or
|
||||||
// defineLazyScriptGetter (and map to
|
// defineLazyScriptGetter (and map to
|
||||||
// single) variable.
|
// single) variable.
|
||||||
{name: "XPCOMUtils", writable: false},
|
{ name: "XPCOMUtils", writable: false },
|
||||||
{name: "Task", writable: false},
|
{ name: "Task", writable: false },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Some files in global-scripts.inc need mapping to specific locations.
|
// Some files in global-scripts.inc need mapping to specific locations.
|
||||||
|
|
@ -51,13 +51,12 @@ const MAPPINGS = {
|
||||||
"places-tree.js": "browser/components/places/content/places-tree.js",
|
"places-tree.js": "browser/components/places/content/places-tree.js",
|
||||||
};
|
};
|
||||||
|
|
||||||
const globalScriptsRegExp =
|
const globalScriptsRegExp = /^\s*Services.scriptloader.loadSubScript\(\"(.*?)\", this\);$/;
|
||||||
/^\s*Services.scriptloader.loadSubScript\(\"(.*?)\", this\);$/;
|
|
||||||
|
|
||||||
function getGlobalScriptIncludes(scriptPath) {
|
function getGlobalScriptIncludes(scriptPath) {
|
||||||
let fileData;
|
let fileData;
|
||||||
try {
|
try {
|
||||||
fileData = fs.readFileSync(scriptPath, {encoding: "utf8"});
|
fileData = fs.readFileSync(scriptPath, { encoding: "utf8" });
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// The file isn't present, so this isn't an m-c repository.
|
// The file isn't present, so this isn't an m-c repository.
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -71,9 +70,12 @@ function getGlobalScriptIncludes(scriptPath) {
|
||||||
let match = line.match(globalScriptsRegExp);
|
let match = line.match(globalScriptsRegExp);
|
||||||
if (match) {
|
if (match) {
|
||||||
let sourceFile = match[1]
|
let sourceFile = match[1]
|
||||||
.replace("chrome://browser/content/search/", "browser/components/search/content/")
|
.replace(
|
||||||
.replace("chrome://browser/content/", "browser/base/content/")
|
"chrome://browser/content/search/",
|
||||||
.replace("chrome://global/content/", "toolkit/content/");
|
"browser/components/search/content/"
|
||||||
|
)
|
||||||
|
.replace("chrome://browser/content/", "browser/base/content/")
|
||||||
|
.replace("chrome://global/content/", "toolkit/content/");
|
||||||
|
|
||||||
for (let mapping of Object.getOwnPropertyNames(MAPPINGS)) {
|
for (let mapping of Object.getOwnPropertyNames(MAPPINGS)) {
|
||||||
if (sourceFile.includes(mapping)) {
|
if (sourceFile.includes(mapping)) {
|
||||||
|
|
@ -110,7 +112,8 @@ function getScriptGlobals() {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Could not load globals from file ${fileName}: ${e}`);
|
console.error(`Could not load globals from file ${fileName}: ${e}`);
|
||||||
console.error(
|
console.error(
|
||||||
`You may need to update the mappings in ${module.filename}`);
|
`You may need to update the mappings in ${module.filename}`
|
||||||
|
);
|
||||||
throw new Error(`Could not load globals from file ${fileName}: ${e}`);
|
throw new Error(`Could not load globals from file ${fileName}: ${e}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -133,6 +136,6 @@ function getMozillaCentralItems() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = helpers.isMozillaCentralBased() ?
|
module.exports = helpers.isMozillaCentralBased()
|
||||||
getMozillaCentralItems() :
|
? getMozillaCentralItems()
|
||||||
helpers.getSavedEnvironmentItems("browser-window");
|
: helpers.getSavedEnvironmentItems("browser-window");
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,12 @@
|
||||||
var globals = require("globals");
|
var globals = require("globals");
|
||||||
var util = require("util");
|
var util = require("util");
|
||||||
|
|
||||||
var workerGlobals = util._extend({
|
var workerGlobals = util._extend(
|
||||||
ctypes: false,
|
{
|
||||||
}, globals.worker);
|
ctypes: false,
|
||||||
|
},
|
||||||
|
globals.worker
|
||||||
|
);
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
globals: workerGlobals,
|
globals: workerGlobals,
|
||||||
|
|
|
||||||
|
|
@ -9,16 +9,16 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"globals": {
|
globals: {
|
||||||
// These globals are hard-coded and available in .jsm scopes.
|
// These globals are hard-coded and available in .jsm scopes.
|
||||||
// https://searchfox.org/mozilla-central/rev/ed212c79cfe86357e9a5740082b9364e7f6e526f/js/xpconnect/loader/mozJSComponentLoader.cpp#134-140
|
// https://searchfox.org/mozilla-central/rev/ed212c79cfe86357e9a5740082b9364e7f6e526f/js/xpconnect/loader/mozJSComponentLoader.cpp#134-140
|
||||||
"atob": false,
|
atob: false,
|
||||||
"btoa": false,
|
btoa: false,
|
||||||
"debug": false,
|
debug: false,
|
||||||
"dump": false,
|
dump: false,
|
||||||
// The WebAssembly global is available in most (if not all) contexts where
|
// The WebAssembly global is available in most (if not all) contexts where
|
||||||
// JS can run. It's definitely available in JSMs. So even if this is not
|
// JS can run. It's definitely available in JSMs. So even if this is not
|
||||||
// the perfect place to add it, it's not wrong, and we can move it later.
|
// the perfect place to add it, it's not wrong, and we can move it later.
|
||||||
"WebAssembly": false,
|
WebAssembly: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -54,7 +54,7 @@ function mapGlobals(fileGlobals) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
globals: helpers.isMozillaCentralBased() ?
|
globals: helpers.isMozillaCentralBased()
|
||||||
mapGlobals(getScriptGlobals()) :
|
? mapGlobals(getScriptGlobals())
|
||||||
helpers.getSavedEnvironmentItems("simpletest").globals,
|
: helpers.getSavedEnvironmentItems("simpletest").globals,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ function parseBooleanConfig(string, comment) {
|
||||||
}
|
}
|
||||||
|
|
||||||
items[name] = {
|
items[name] = {
|
||||||
value: (value === "true"),
|
value: value === "true",
|
||||||
comment,
|
comment,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
@ -135,7 +135,10 @@ GlobalsForNode.prototype = {
|
||||||
// Note: We check the expression types here and only call the necessary
|
// Note: We check the expression types here and only call the necessary
|
||||||
// functions to aid performance.
|
// functions to aid performance.
|
||||||
if (node.expression.type === "AssignmentExpression") {
|
if (node.expression.type === "AssignmentExpression") {
|
||||||
globals = helpers.convertThisAssignmentExpressionToGlobals(node, isGlobal);
|
globals = helpers.convertThisAssignmentExpressionToGlobals(
|
||||||
|
node,
|
||||||
|
isGlobal
|
||||||
|
);
|
||||||
} else if (node.expression.type === "CallExpression") {
|
} else if (node.expression.type === "CallExpression") {
|
||||||
globals = helpers.convertCallExpressionToGlobals(node, isGlobal);
|
globals = helpers.convertCallExpressionToGlobals(node, isGlobal);
|
||||||
}
|
}
|
||||||
|
|
@ -144,8 +147,11 @@ GlobalsForNode.prototype = {
|
||||||
// this is a worker. It would be nice if eslint gave us a way of getting
|
// this is a worker. It would be nice if eslint gave us a way of getting
|
||||||
// the environment directly.
|
// the environment directly.
|
||||||
if (globalScope && globalScope.set.get("importScripts")) {
|
if (globalScope && globalScope.set.get("importScripts")) {
|
||||||
let workerDetails = helpers.convertWorkerExpressionToGlobals(node,
|
let workerDetails = helpers.convertWorkerExpressionToGlobals(
|
||||||
isGlobal, this.dirname);
|
node,
|
||||||
|
isGlobal,
|
||||||
|
this.dirname
|
||||||
|
);
|
||||||
globals = globals.concat(workerDetails);
|
globals = globals.concat(workerDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,19 +271,31 @@ module.exports = {
|
||||||
} else if (script.src.includes("chrome")) {
|
} else if (script.src.includes("chrome")) {
|
||||||
// This is one way of referencing test files.
|
// This is one way of referencing test files.
|
||||||
script.src = script.src.replace("chrome://mochikit/content/", "/");
|
script.src = script.src.replace("chrome://mochikit/content/", "/");
|
||||||
scriptName = path.join(helpers.rootDir, "testing", "mochitest", script.src);
|
scriptName = path.join(
|
||||||
|
helpers.rootDir,
|
||||||
|
"testing",
|
||||||
|
"mochitest",
|
||||||
|
script.src
|
||||||
|
);
|
||||||
} else if (script.src.includes("SimpleTest")) {
|
} else if (script.src.includes("SimpleTest")) {
|
||||||
// This is another way of referencing test files...
|
// This is another way of referencing test files...
|
||||||
scriptName = path.join(helpers.rootDir, "testing", "mochitest", script.src);
|
scriptName = path.join(
|
||||||
|
helpers.rootDir,
|
||||||
|
"testing",
|
||||||
|
"mochitest",
|
||||||
|
script.src
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Fallback to hoping this is a relative path.
|
// Fallback to hoping this is a relative path.
|
||||||
scriptName = path.join(dir, script.src);
|
scriptName = path.join(dir, script.src);
|
||||||
}
|
}
|
||||||
if (scriptName && fs.existsSync(scriptName)) {
|
if (scriptName && fs.existsSync(scriptName)) {
|
||||||
globals.push(...module.exports.getGlobalsForFile(scriptName, {
|
globals.push(
|
||||||
ecmaVersion: helpers.getECMAVersion(),
|
...module.exports.getGlobalsForFile(scriptName, {
|
||||||
sourceType: script.type,
|
ecmaVersion: helpers.getECMAVersion(),
|
||||||
}));
|
sourceType: script.type,
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,7 +335,11 @@ module.exports = {
|
||||||
helpers.addGlobals(extraHTMLGlobals, globalScope);
|
helpers.addGlobals(extraHTMLGlobals, globalScope);
|
||||||
}
|
}
|
||||||
let globals = handler[type](node, context.getAncestors(), globalScope);
|
let globals = handler[type](node, context.getAncestors(), globalScope);
|
||||||
helpers.addGlobals(globals, globalScope, node.type !== "Program" && node);
|
helpers.addGlobals(
|
||||||
|
globals,
|
||||||
|
globalScope,
|
||||||
|
node.type !== "Program" && node
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,13 @@ module.exports = {
|
||||||
get modulesGlobalData() {
|
get modulesGlobalData() {
|
||||||
if (!gModules) {
|
if (!gModules) {
|
||||||
if (this.isMozillaCentralBased()) {
|
if (this.isMozillaCentralBased()) {
|
||||||
gModules = require(path.join(this.rootDir, "tools", "lint", "eslint", "modules.json"));
|
gModules = require(path.join(
|
||||||
|
this.rootDir,
|
||||||
|
"tools",
|
||||||
|
"lint",
|
||||||
|
"eslint",
|
||||||
|
"modules.json"
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
gModules = require("./modules.json");
|
gModules = require("./modules.json");
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +84,7 @@ module.exports = {
|
||||||
getAST(sourceText, astOptions = {}) {
|
getAST(sourceText, astOptions = {}) {
|
||||||
// Use a permissive config file to allow parsing of anything that Espree
|
// Use a permissive config file to allow parsing of anything that Espree
|
||||||
// can parse.
|
// can parse.
|
||||||
let config = {...this.getPermissiveConfig(), ...astOptions};
|
let config = { ...this.getPermissiveConfig(), ...astOptions };
|
||||||
|
|
||||||
return espree.parse(sourceText, config);
|
return espree.parse(sourceText, config);
|
||||||
},
|
},
|
||||||
|
|
@ -97,10 +103,15 @@ module.exports = {
|
||||||
case "MemberExpression":
|
case "MemberExpression":
|
||||||
if (node.computed) {
|
if (node.computed) {
|
||||||
let filename = context && context.getFilename();
|
let filename = context && context.getFilename();
|
||||||
throw new Error(`getASTSource unsupported computed MemberExpression in ${filename}`);
|
throw new Error(
|
||||||
|
`getASTSource unsupported computed MemberExpression in ${filename}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return this.getASTSource(node.object) + "." +
|
return (
|
||||||
this.getASTSource(node.property);
|
this.getASTSource(node.object) +
|
||||||
|
"." +
|
||||||
|
this.getASTSource(node.property)
|
||||||
|
);
|
||||||
case "ThisExpression":
|
case "ThisExpression":
|
||||||
return "this";
|
return "this";
|
||||||
case "Identifier":
|
case "Identifier":
|
||||||
|
|
@ -121,10 +132,17 @@ module.exports = {
|
||||||
case "ArrowFunctionExpression":
|
case "ArrowFunctionExpression":
|
||||||
return "() => {}";
|
return "() => {}";
|
||||||
case "AssignmentExpression":
|
case "AssignmentExpression":
|
||||||
return this.getASTSource(node.left) + " = " +
|
return (
|
||||||
this.getASTSource(node.right);
|
this.getASTSource(node.left) + " = " + this.getASTSource(node.right)
|
||||||
|
);
|
||||||
case "BinaryExpression":
|
case "BinaryExpression":
|
||||||
return this.getASTSource(node.left) + " " + node.operator + " " + this.getASTSource(node.right);
|
return (
|
||||||
|
this.getASTSource(node.left) +
|
||||||
|
" " +
|
||||||
|
node.operator +
|
||||||
|
" " +
|
||||||
|
this.getASTSource(node.right)
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
throw new Error("getASTSource unsupported node type: " + node.type);
|
throw new Error("getASTSource unsupported node type: " + node.type);
|
||||||
}
|
}
|
||||||
|
|
@ -187,10 +205,12 @@ module.exports = {
|
||||||
let results = [];
|
let results = [];
|
||||||
let expr = node.expression;
|
let expr = node.expression;
|
||||||
|
|
||||||
if (node.expression.type === "CallExpression" &&
|
if (
|
||||||
expr.callee &&
|
node.expression.type === "CallExpression" &&
|
||||||
expr.callee.type === "Identifier" &&
|
expr.callee &&
|
||||||
expr.callee.name === "importScripts") {
|
expr.callee.type === "Identifier" &&
|
||||||
|
expr.callee.name === "importScripts"
|
||||||
|
) {
|
||||||
for (var arg of expr.arguments) {
|
for (var arg of expr.arguments) {
|
||||||
var match = arg.value && arg.value.match(workerImportFilenameMatch);
|
var match = arg.value && arg.value.match(workerImportFilenameMatch);
|
||||||
if (match) {
|
if (match) {
|
||||||
|
|
@ -201,9 +221,11 @@ module.exports = {
|
||||||
results = results.concat(additionalGlobals);
|
results = results.concat(additionalGlobals);
|
||||||
}
|
}
|
||||||
} else if (match[2] in globalModules) {
|
} else if (match[2] in globalModules) {
|
||||||
results = results.concat(globalModules[match[2]].map(name => {
|
results = results.concat(
|
||||||
return { name, writable: true };
|
globalModules[match[2]].map(name => {
|
||||||
}));
|
return { name, writable: true };
|
||||||
|
})
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
results.push({ name: match[3], writable: true, explicit: true });
|
results.push({ name: match[3], writable: true, explicit: true });
|
||||||
}
|
}
|
||||||
|
|
@ -231,12 +253,14 @@ module.exports = {
|
||||||
* If the global is writeable or not.
|
* If the global is writeable or not.
|
||||||
*/
|
*/
|
||||||
convertThisAssignmentExpressionToGlobals(node, isGlobal) {
|
convertThisAssignmentExpressionToGlobals(node, isGlobal) {
|
||||||
if (isGlobal &&
|
if (
|
||||||
node.expression.left &&
|
isGlobal &&
|
||||||
node.expression.left.object &&
|
node.expression.left &&
|
||||||
node.expression.left.object.type === "ThisExpression" &&
|
node.expression.left.object &&
|
||||||
node.expression.left.property &&
|
node.expression.left.object.type === "ThisExpression" &&
|
||||||
node.expression.left.property.type === "Identifier") {
|
node.expression.left.property &&
|
||||||
|
node.expression.left.property.type === "Identifier"
|
||||||
|
) {
|
||||||
return [{ name: node.expression.left.property.name, writable: true }];
|
return [{ name: node.expression.left.property.name, writable: true }];
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
|
|
@ -260,14 +284,16 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
convertCallExpressionToGlobals(node, isGlobal) {
|
convertCallExpressionToGlobals(node, isGlobal) {
|
||||||
let express = node.expression;
|
let express = node.expression;
|
||||||
if (express.type === "CallExpression" &&
|
if (
|
||||||
express.callee.type === "MemberExpression" &&
|
express.type === "CallExpression" &&
|
||||||
express.callee.object &&
|
express.callee.type === "MemberExpression" &&
|
||||||
express.callee.object.type === "Identifier" &&
|
express.callee.object &&
|
||||||
express.arguments.length === 1 &&
|
express.callee.object.type === "Identifier" &&
|
||||||
express.arguments[0].type === "ArrayExpression" &&
|
express.arguments.length === 1 &&
|
||||||
express.callee.property.type === "Identifier" &&
|
express.arguments[0].type === "ArrayExpression" &&
|
||||||
express.callee.property.name === "importGlobalProperties") {
|
express.callee.property.type === "Identifier" &&
|
||||||
|
express.callee.property.name === "importGlobalProperties"
|
||||||
|
) {
|
||||||
return express.arguments[0].elements.map(literal => {
|
return express.arguments[0].elements.map(literal => {
|
||||||
return {
|
return {
|
||||||
explicit: true,
|
explicit: true,
|
||||||
|
|
@ -301,7 +327,9 @@ module.exports = {
|
||||||
// of them.
|
// of them.
|
||||||
let explicit = globalModules[match[1]].length == 1;
|
let explicit = globalModules[match[1]].length == 1;
|
||||||
return globalModules[match[1]].map(name => ({
|
return globalModules[match[1]].map(name => ({
|
||||||
name, writable: true, explicit,
|
name,
|
||||||
|
writable: true,
|
||||||
|
explicit,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,27 +350,43 @@ module.exports = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callExpressionMultiDefinitions.some(expr => source.startsWith(expr)) &&
|
if (
|
||||||
node.expression.arguments[1]) {
|
callExpressionMultiDefinitions.some(expr => source.startsWith(expr)) &&
|
||||||
|
node.expression.arguments[1]
|
||||||
|
) {
|
||||||
let arg = node.expression.arguments[1];
|
let arg = node.expression.arguments[1];
|
||||||
if (arg.type === "ObjectExpression") {
|
if (arg.type === "ObjectExpression") {
|
||||||
return arg.properties
|
return arg.properties
|
||||||
.map(p => ({ name: p.type === "Property" && p.key.name, writable: true, explicit: true }))
|
.map(p => ({
|
||||||
.filter(g => g.name);
|
name: p.type === "Property" && p.key.name,
|
||||||
|
writable: true,
|
||||||
|
explicit: true,
|
||||||
|
}))
|
||||||
|
.filter(g => g.name);
|
||||||
}
|
}
|
||||||
if (arg.type === "ArrayExpression") {
|
if (arg.type === "ArrayExpression") {
|
||||||
return arg.elements
|
return arg.elements
|
||||||
.map(p => ({ name: p.type === "Literal" && p.value, writable: true, explicit: true }))
|
.map(p => ({
|
||||||
.filter(g => typeof g.name == "string");
|
name: p.type === "Literal" && p.value,
|
||||||
|
writable: true,
|
||||||
|
explicit: true,
|
||||||
|
}))
|
||||||
|
.filter(g => typeof g.name == "string");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.expression.callee.type == "MemberExpression" &&
|
if (
|
||||||
node.expression.callee.property.type == "Identifier" &&
|
node.expression.callee.type == "MemberExpression" &&
|
||||||
node.expression.callee.property.name == "defineLazyScriptGetter") {
|
node.expression.callee.property.type == "Identifier" &&
|
||||||
|
node.expression.callee.property.name == "defineLazyScriptGetter"
|
||||||
|
) {
|
||||||
// The case where we have a single symbol as a string has already been
|
// The case where we have a single symbol as a string has already been
|
||||||
// handled by the regexp, so we have an array of symbols here.
|
// handled by the regexp, so we have an array of symbols here.
|
||||||
return node.expression.arguments[1].elements.map(n => ({ name: n.value, writable: true, explicit: true }));
|
return node.expression.arguments[1].elements.map(n => ({
|
||||||
|
name: n.value,
|
||||||
|
writable: true,
|
||||||
|
explicit: true,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
|
|
@ -368,7 +412,7 @@ module.exports = {
|
||||||
variable.eslintExplicitGlobal = false;
|
variable.eslintExplicitGlobal = false;
|
||||||
variable.writeable = writable;
|
variable.writeable = writable;
|
||||||
if (node) {
|
if (node) {
|
||||||
variable.defs.push({node, name: {name}});
|
variable.defs.push({ node, name: { name } });
|
||||||
variable.identifiers.push(node);
|
variable.identifiers.push(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -402,7 +446,9 @@ module.exports = {
|
||||||
* The AST node that defined the globals.
|
* The AST node that defined the globals.
|
||||||
*/
|
*/
|
||||||
addGlobals(globalVars, scope, node) {
|
addGlobals(globalVars, scope, node) {
|
||||||
globalVars.forEach(v => this.addVarToScope(v.name, scope, v.writable, v.explicit && node));
|
globalVars.forEach(v =>
|
||||||
|
this.addVarToScope(v.name, scope, v.writable, v.explicit && node)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -503,11 +549,14 @@ module.exports = {
|
||||||
let filepath = this.cleanUpPath(scope.getFilename());
|
let filepath = this.cleanUpPath(scope.getFilename());
|
||||||
let dir = path.dirname(filepath);
|
let dir = path.dirname(filepath);
|
||||||
|
|
||||||
let names =
|
let names = fs
|
||||||
fs.readdirSync(dir)
|
.readdirSync(dir)
|
||||||
.filter(name => (name.startsWith("head") ||
|
.filter(
|
||||||
name.startsWith("xpcshell-head")) && name.endsWith(".js"))
|
name =>
|
||||||
.map(name => path.join(dir, name));
|
(name.startsWith("head") || name.startsWith("xpcshell-head")) &&
|
||||||
|
name.endsWith(".js")
|
||||||
|
)
|
||||||
|
.map(name => path.join(dir, name));
|
||||||
return names;
|
return names;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -548,8 +597,7 @@ module.exports = {
|
||||||
file: path.join(dir, name),
|
file: path.join(dir, name),
|
||||||
manifest,
|
manifest,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
directoryManifests.set(dir, manifests);
|
directoryManifests.set(dir, manifests);
|
||||||
|
|
@ -673,7 +721,10 @@ module.exports = {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let possibleRoot = searchUpForIgnore(path.dirname(module.filename), ".eslintignore");
|
let possibleRoot = searchUpForIgnore(
|
||||||
|
path.dirname(module.filename),
|
||||||
|
".eslintignore"
|
||||||
|
);
|
||||||
if (!possibleRoot) {
|
if (!possibleRoot) {
|
||||||
possibleRoot = searchUpForIgnore(path.resolve(), ".eslintignore");
|
possibleRoot = searchUpForIgnore(path.resolve(), ".eslintignore");
|
||||||
}
|
}
|
||||||
|
|
@ -717,9 +768,9 @@ module.exports = {
|
||||||
// without any path info (happens in Atom with linter-eslint)
|
// without any path info (happens in Atom with linter-eslint)
|
||||||
return path.join(cwd, fileName);
|
return path.join(cwd, fileName);
|
||||||
}
|
}
|
||||||
// Case 1: executed form in a nested directory, e.g. from a text editor:
|
// Case 1: executed form in a nested directory, e.g. from a text editor:
|
||||||
// fileName: a/b/c/d.js
|
// fileName: a/b/c/d.js
|
||||||
// cwd: /path/to/mozilla/repo/a/b/c
|
// cwd: /path/to/mozilla/repo/a/b/c
|
||||||
var dirName = path.dirname(fileName);
|
var dirName = path.dirname(fileName);
|
||||||
return cwd.slice(0, cwd.length - dirName.length) + fileName;
|
return cwd.slice(0, cwd.length - dirName.length) + fileName;
|
||||||
},
|
},
|
||||||
|
|
@ -736,7 +787,13 @@ module.exports = {
|
||||||
get globalScriptPaths() {
|
get globalScriptPaths() {
|
||||||
return [
|
return [
|
||||||
path.join(this.rootDir, "browser", "base", "content", "browser.xhtml"),
|
path.join(this.rootDir, "browser", "base", "content", "browser.xhtml"),
|
||||||
path.join(this.rootDir, "browser", "base", "content", "global-scripts.inc"),
|
path.join(
|
||||||
|
this.rootDir,
|
||||||
|
"browser",
|
||||||
|
"base",
|
||||||
|
"content",
|
||||||
|
"global-scripts.inc"
|
||||||
|
),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -745,7 +802,9 @@ module.exports = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getSavedEnvironmentItems(environment) {
|
getSavedEnvironmentItems(environment) {
|
||||||
return require("./environments/saved-globals.json").environments[environment];
|
return require("./environments/saved-globals.json").environments[
|
||||||
|
environment
|
||||||
|
];
|
||||||
},
|
},
|
||||||
|
|
||||||
getSavedRuleData(rule) {
|
getSavedRuleData(rule) {
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,16 @@ module.exports = {
|
||||||
"browser-test": require("../lib/configs/browser-test"),
|
"browser-test": require("../lib/configs/browser-test"),
|
||||||
"chrome-test": require("../lib/configs/chrome-test"),
|
"chrome-test": require("../lib/configs/chrome-test"),
|
||||||
"mochitest-test": require("../lib/configs/mochitest-test"),
|
"mochitest-test": require("../lib/configs/mochitest-test"),
|
||||||
"recommended": require("../lib/configs/recommended"),
|
recommended: require("../lib/configs/recommended"),
|
||||||
"xpcshell-test": require("../lib/configs/xpcshell-test"),
|
"xpcshell-test": require("../lib/configs/xpcshell-test"),
|
||||||
},
|
},
|
||||||
environments: {
|
environments: {
|
||||||
"browser-window": require("../lib/environments/browser-window.js"),
|
"browser-window": require("../lib/environments/browser-window.js"),
|
||||||
"chrome-worker": require("../lib/environments/chrome-worker.js"),
|
"chrome-worker": require("../lib/environments/chrome-worker.js"),
|
||||||
"frame-script": require("../lib/environments/frame-script.js"),
|
"frame-script": require("../lib/environments/frame-script.js"),
|
||||||
"jsm": require("../lib/environments/jsm.js"),
|
jsm: require("../lib/environments/jsm.js"),
|
||||||
"simpletest": require("../lib/environments/simpletest.js"),
|
simpletest: require("../lib/environments/simpletest.js"),
|
||||||
"privileged": require("../lib/environments/privileged.js"),
|
privileged: require("../lib/environments/privileged.js"),
|
||||||
},
|
},
|
||||||
processors: {
|
processors: {
|
||||||
".xml": require("../lib/processors/xbl-bindings"),
|
".xml": require("../lib/processors/xbl-bindings"),
|
||||||
|
|
@ -36,10 +36,8 @@ module.exports = {
|
||||||
"avoid-removeChild": require("../lib/rules/avoid-removeChild"),
|
"avoid-removeChild": require("../lib/rules/avoid-removeChild"),
|
||||||
"balanced-listeners": require("../lib/rules/balanced-listeners"),
|
"balanced-listeners": require("../lib/rules/balanced-listeners"),
|
||||||
"consistent-if-bracing": require("../lib/rules/consistent-if-bracing"),
|
"consistent-if-bracing": require("../lib/rules/consistent-if-bracing"),
|
||||||
"import-browser-window-globals":
|
"import-browser-window-globals": require("../lib/rules/import-browser-window-globals"),
|
||||||
require("../lib/rules/import-browser-window-globals"),
|
"import-content-task-globals": require("../lib/rules/import-content-task-globals"),
|
||||||
"import-content-task-globals":
|
|
||||||
require("../lib/rules/import-content-task-globals"),
|
|
||||||
"import-globals": require("../lib/rules/import-globals"),
|
"import-globals": require("../lib/rules/import-globals"),
|
||||||
"import-headjs-globals": require("../lib/rules/import-headjs-globals"),
|
"import-headjs-globals": require("../lib/rules/import-headjs-globals"),
|
||||||
"mark-exported-symbols-as-used": require("../lib/rules/mark-exported-symbols-as-used"),
|
"mark-exported-symbols-as-used": require("../lib/rules/mark-exported-symbols-as-used"),
|
||||||
|
|
@ -50,19 +48,15 @@ module.exports = {
|
||||||
"no-define-cc-etc": require("../lib/rules/no-define-cc-etc"),
|
"no-define-cc-etc": require("../lib/rules/no-define-cc-etc"),
|
||||||
"no-task": require("../lib/rules/no-task"),
|
"no-task": require("../lib/rules/no-task"),
|
||||||
"no-useless-parameters": require("../lib/rules/no-useless-parameters"),
|
"no-useless-parameters": require("../lib/rules/no-useless-parameters"),
|
||||||
"no-useless-removeEventListener":
|
"no-useless-removeEventListener": require("../lib/rules/no-useless-removeEventListener"),
|
||||||
require("../lib/rules/no-useless-removeEventListener"),
|
"no-useless-run-test": require("../lib/rules/no-useless-run-test"),
|
||||||
"no-useless-run-test":
|
"reject-importGlobalProperties": require("../lib/rules/reject-importGlobalProperties"),
|
||||||
require("../lib/rules/no-useless-run-test"),
|
|
||||||
"reject-importGlobalProperties":
|
|
||||||
require("../lib/rules/reject-importGlobalProperties"),
|
|
||||||
"reject-some-requires": require("../lib/rules/reject-some-requires"),
|
"reject-some-requires": require("../lib/rules/reject-some-requires"),
|
||||||
"rejects-requires-await": require("../lib/rules/rejects-requires-await"),
|
"rejects-requires-await": require("../lib/rules/rejects-requires-await"),
|
||||||
"use-cc-etc": require("../lib/rules/use-cc-etc"),
|
"use-cc-etc": require("../lib/rules/use-cc-etc"),
|
||||||
"use-chromeutils-generateqi": require("../lib/rules/use-chromeutils-generateqi"),
|
"use-chromeutils-generateqi": require("../lib/rules/use-chromeutils-generateqi"),
|
||||||
"use-chromeutils-import": require("../lib/rules/use-chromeutils-import"),
|
"use-chromeutils-import": require("../lib/rules/use-chromeutils-import"),
|
||||||
"use-default-preference-values":
|
"use-default-preference-values": require("../lib/rules/use-default-preference-values"),
|
||||||
require("../lib/rules/use-default-preference-values"),
|
|
||||||
"use-ownerGlobal": require("../lib/rules/use-ownerGlobal"),
|
"use-ownerGlobal": require("../lib/rules/use-ownerGlobal"),
|
||||||
"use-includes-instead-of-indexOf": require("../lib/rules/use-includes-instead-of-indexOf"),
|
"use-includes-instead-of-indexOf": require("../lib/rules/use-includes-instead-of-indexOf"),
|
||||||
"use-returnValue": require("../lib/rules/use-returnValue"),
|
"use-returnValue": require("../lib/rules/use-returnValue"),
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,11 @@ function addNodeLines(node, reindent) {
|
||||||
|
|
||||||
// If the second to last line is also blank and has a higher indent than the
|
// If the second to last line is also blank and has a higher indent than the
|
||||||
// last one, then the CDATA block doesn't close with the closing tag.
|
// last one, then the CDATA block doesn't close with the closing tag.
|
||||||
if (lines.length > 2 && lines[lines.length - 2].trim() == "" &&
|
if (
|
||||||
lines[lines.length - 2].length > lastIndent) {
|
lines.length > 2 &&
|
||||||
|
lines[lines.length - 2].trim() == "" &&
|
||||||
|
lines[lines.length - 2].length > lastIndent
|
||||||
|
) {
|
||||||
lastIndent = lines[lines.length - 2].length;
|
lastIndent = lines[lines.length - 2].length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,8 +85,9 @@ function addNodeLines(node, reindent) {
|
||||||
|
|
||||||
// Find the preceding whitespace for all lines that aren't entirely
|
// Find the preceding whitespace for all lines that aren't entirely
|
||||||
// whitespace.
|
// whitespace.
|
||||||
let indents = lines.filter(s => s.trim().length > 0)
|
let indents = lines
|
||||||
.map(s => s.length - s.trimLeft().length);
|
.filter(s => s.trim().length > 0)
|
||||||
|
.map(s => s.length - s.trimLeft().length);
|
||||||
// Find the smallest indent level in use
|
// Find the smallest indent level in use
|
||||||
let minIndent = Math.min.apply(null, indents);
|
let minIndent = Math.min.apply(null, indents);
|
||||||
let indent = Math.max(2, minIndent - lastIndent);
|
let indent = Math.max(2, minIndent - lastIndent);
|
||||||
|
|
@ -172,7 +176,10 @@ module.exports = {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
addSyntheticLine(`get ${item.attributes.name}() {`, item.textLine);
|
addSyntheticLine(
|
||||||
|
`get ${item.attributes.name}() {`,
|
||||||
|
item.textLine
|
||||||
|
);
|
||||||
addSyntheticLine(`return (`, item.textLine);
|
addSyntheticLine(`return (`, item.textLine);
|
||||||
|
|
||||||
// Remove trailing semicolons, as we are adding our own
|
// Remove trailing semicolons, as we are adding our own
|
||||||
|
|
@ -195,16 +202,20 @@ module.exports = {
|
||||||
// Methods become function declarations with the appropriate
|
// Methods become function declarations with the appropriate
|
||||||
// params.
|
// params.
|
||||||
|
|
||||||
let params = item.children.filter(n => {
|
let params = item.children
|
||||||
return n.local == "parameter" && n.namespace == NS_XBL;
|
.filter(n => {
|
||||||
})
|
return n.local == "parameter" && n.namespace == NS_XBL;
|
||||||
.map(n => n.attributes.name)
|
})
|
||||||
.join(", ");
|
.map(n => n.attributes.name)
|
||||||
|
.join(", ");
|
||||||
let body = item.children.filter(n => {
|
let body = item.children.filter(n => {
|
||||||
return n.local == "body" && n.namespace == NS_XBL;
|
return n.local == "body" && n.namespace == NS_XBL;
|
||||||
})[0];
|
})[0];
|
||||||
|
|
||||||
addSyntheticLine(`${item.attributes.name}(${params}) {`, item.textLine);
|
addSyntheticLine(
|
||||||
|
`${item.attributes.name}(${params}) {`,
|
||||||
|
item.textLine
|
||||||
|
);
|
||||||
addNodeLines(body, 4);
|
addNodeLines(body, 4);
|
||||||
addSyntheticLine(`},`, item.textEndLine);
|
addSyntheticLine(`},`, item.textEndLine);
|
||||||
break;
|
break;
|
||||||
|
|
@ -217,9 +228,15 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propdef.local == "setter") {
|
if (propdef.local == "setter") {
|
||||||
addSyntheticLine(`set ${item.attributes.name}(val) {`, propdef.textLine);
|
addSyntheticLine(
|
||||||
|
`set ${item.attributes.name}(val) {`,
|
||||||
|
propdef.textLine
|
||||||
|
);
|
||||||
} else if (propdef.local == "getter") {
|
} else if (propdef.local == "getter") {
|
||||||
addSyntheticLine(`get ${item.attributes.name}() {`, propdef.textLine);
|
addSyntheticLine(
|
||||||
|
`get ${item.attributes.name}() {`,
|
||||||
|
propdef.textLine
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -241,7 +258,10 @@ module.exports = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addSyntheticLine((part.local == "implementation" ? `},` : `],`), part.textEndLine);
|
addSyntheticLine(
|
||||||
|
part.local == "implementation" ? `},` : `],`,
|
||||||
|
part.textEndLine
|
||||||
|
);
|
||||||
}
|
}
|
||||||
addSyntheticLine(`},`, binding.textEndLine);
|
addSyntheticLine(`},`, binding.textEndLine);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,12 @@ function dealWithIfdefs(text, filename) {
|
||||||
if (!line.startsWith("#")) {
|
if (!line.startsWith("#")) {
|
||||||
outputLines.push(shouldSkip ? "" : line);
|
outputLines.push(shouldSkip ? "" : line);
|
||||||
} else {
|
} else {
|
||||||
if (line.startsWith("# ") || line.startsWith("#filter") ||
|
if (
|
||||||
line == "#" || line.startsWith("#define")) {
|
line.startsWith("# ") ||
|
||||||
|
line.startsWith("#filter") ||
|
||||||
|
line == "#" ||
|
||||||
|
line.startsWith("#define")
|
||||||
|
) {
|
||||||
outputLines.push("");
|
outputLines.push("");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +90,7 @@ function dealWithIfdefs(text, filename) {
|
||||||
if (!shouldSkip) {
|
if (!shouldSkip) {
|
||||||
let fileToInclude = line.substr("#include ".length).trim();
|
let fileToInclude = line.substr("#include ".length).trim();
|
||||||
let subpath = path.join(path.dirname(innerFile), fileToInclude);
|
let subpath = path.join(path.dirname(innerFile), fileToInclude);
|
||||||
let contents = fs.readFileSync(subpath, {encoding: "utf-8"});
|
let contents = fs.readFileSync(subpath, { encoding: "utf-8" });
|
||||||
contents = contents.split(/\n/);
|
contents = contents.split(/\n/);
|
||||||
// Recurse:
|
// Recurse:
|
||||||
contents = stripIfdefsFromLines(contents, subpath);
|
contents = stripIfdefsFromLines(contents, subpath);
|
||||||
|
|
@ -188,7 +192,7 @@ module.exports = {
|
||||||
"/* eslint-disable quotes */",
|
"/* eslint-disable quotes */",
|
||||||
"/* eslint-disable no-undef */",
|
"/* eslint-disable no-undef */",
|
||||||
];
|
];
|
||||||
lineMap = scriptLines.map(() => ({line: 0}));
|
lineMap = scriptLines.map(() => ({ line: 0 }));
|
||||||
includedRanges = [];
|
includedRanges = [];
|
||||||
// Do C-style preprocessing first:
|
// Do C-style preprocessing first:
|
||||||
text = dealWithIfdefs(text, filename);
|
text = dealWithIfdefs(text, filename);
|
||||||
|
|
@ -225,17 +229,22 @@ module.exports = {
|
||||||
let mapped = lineMap[message.line - 1];
|
let mapped = lineMap[message.line - 1];
|
||||||
// Ensure we don't modify this by making a copy. We might need it for another failure.
|
// Ensure we don't modify this by making a copy. We might need it for another failure.
|
||||||
let target = mapped.line;
|
let target = mapped.line;
|
||||||
let includedRange = includedRanges.find(r => (target >= r.start && target <= r.end));
|
let includedRange = includedRanges.find(
|
||||||
|
r => target >= r.start && target <= r.end
|
||||||
|
);
|
||||||
// If this came from an #included file, indicate this in the message
|
// If this came from an #included file, indicate this in the message
|
||||||
if (includedRange) {
|
if (includedRange) {
|
||||||
target = includedRange.start;
|
target = includedRange.start;
|
||||||
message.message += " (from included file " + path.basename(includedRange.filename) + ")";
|
message.message +=
|
||||||
|
" (from included file " +
|
||||||
|
path.basename(includedRange.filename) +
|
||||||
|
")";
|
||||||
}
|
}
|
||||||
// Compensate for line numbers shifting as a result of #include:
|
// Compensate for line numbers shifting as a result of #include:
|
||||||
let includeBallooning =
|
let includeBallooning = includedRanges
|
||||||
includedRanges.filter(r => (target >= r.end))
|
.filter(r => target >= r.end)
|
||||||
.map(r => r.end - r.start)
|
.map(r => r.end - r.start)
|
||||||
.reduce((acc, next) => acc + next, 0);
|
.reduce((acc, next) => acc + next, 0);
|
||||||
target -= includeBallooning;
|
target -= includeBallooning;
|
||||||
// Add back the 1 to go back to 1-indexing.
|
// Add back the 1 to go back to 1-indexing.
|
||||||
message.line = target + 1;
|
message.line = target + 1;
|
||||||
|
|
@ -250,4 +259,3 @@ module.exports = {
|
||||||
return errors;
|
return errors;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,32 +27,41 @@ module.exports = {
|
||||||
|
|
||||||
create(context) {
|
create(context) {
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
let callee = node.callee;
|
let callee = node.callee;
|
||||||
if (callee.type !== "MemberExpression" ||
|
if (
|
||||||
callee.object.type !== "Identifier" ||
|
callee.type !== "MemberExpression" ||
|
||||||
callee.object.name !== "Date" ||
|
callee.object.type !== "Identifier" ||
|
||||||
callee.property.type !== "Identifier" ||
|
callee.object.name !== "Date" ||
|
||||||
callee.property.name !== "now") {
|
callee.property.type !== "Identifier" ||
|
||||||
|
callee.property.name !== "now"
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.report(node, "use performance.now() instead of Date.now() for timing " +
|
context.report(
|
||||||
"measurements");
|
node,
|
||||||
|
"use performance.now() instead of Date.now() for timing " +
|
||||||
|
"measurements"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
"NewExpression": function(node) {
|
NewExpression(node) {
|
||||||
let callee = node.callee;
|
let callee = node.callee;
|
||||||
if (callee.type !== "Identifier" ||
|
if (
|
||||||
callee.name !== "Date" ||
|
callee.type !== "Identifier" ||
|
||||||
node.arguments.length > 0) {
|
callee.name !== "Date" ||
|
||||||
|
node.arguments.length > 0
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.report(node, "use performance.now() instead of new Date() for timing " +
|
context.report(
|
||||||
"measurements");
|
node,
|
||||||
|
"use performance.now() instead of new Date() for timing " +
|
||||||
|
"measurements"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,31 +21,43 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
let callee = node.callee;
|
let callee = node.callee;
|
||||||
if (callee.type !== "MemberExpression" ||
|
if (
|
||||||
callee.property.type !== "Identifier" ||
|
callee.type !== "MemberExpression" ||
|
||||||
callee.property.name != "removeChild" ||
|
callee.property.type !== "Identifier" ||
|
||||||
node.arguments.length != 1) {
|
callee.property.name != "removeChild" ||
|
||||||
|
node.arguments.length != 1
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callee.object.type == "MemberExpression" &&
|
if (
|
||||||
callee.object.property.type == "Identifier" &&
|
callee.object.type == "MemberExpression" &&
|
||||||
callee.object.property.name == "parentNode" &&
|
callee.object.property.type == "Identifier" &&
|
||||||
helpers.getASTSource(callee.object.object, context) ==
|
callee.object.property.name == "parentNode" &&
|
||||||
helpers.getASTSource(node.arguments[0])) {
|
helpers.getASTSource(callee.object.object, context) ==
|
||||||
context.report(node, "use element.remove() instead of " +
|
helpers.getASTSource(node.arguments[0])
|
||||||
"element.parentNode.removeChild(element)");
|
) {
|
||||||
|
context.report(
|
||||||
|
node,
|
||||||
|
"use element.remove() instead of " +
|
||||||
|
"element.parentNode.removeChild(element)"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.arguments[0].type == "MemberExpression" &&
|
if (
|
||||||
node.arguments[0].property.type == "Identifier" &&
|
node.arguments[0].type == "MemberExpression" &&
|
||||||
node.arguments[0].property.name == "firstChild" &&
|
node.arguments[0].property.type == "Identifier" &&
|
||||||
helpers.getASTSource(callee.object, context) ==
|
node.arguments[0].property.name == "firstChild" &&
|
||||||
helpers.getASTSource(node.arguments[0].object)) {
|
helpers.getASTSource(callee.object, context) ==
|
||||||
context.report(node, "use element.firstChild.remove() instead of " +
|
helpers.getASTSource(node.arguments[0].object)
|
||||||
"element.removeChild(element.firstChild)");
|
) {
|
||||||
|
context.report(
|
||||||
|
node,
|
||||||
|
"use element.firstChild.remove() instead of " +
|
||||||
|
"element.removeChild(element.firstChild)"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ module.exports = function(context) {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
var DICTIONARY = {
|
var DICTIONARY = {
|
||||||
"addEventListener": "removeEventListener",
|
addEventListener: "removeEventListener",
|
||||||
"on": "off",
|
on: "off",
|
||||||
};
|
};
|
||||||
// Invert this dictionary to make it easy later.
|
// Invert this dictionary to make it easy later.
|
||||||
var INVERTED_DICTIONARY = {};
|
var INVERTED_DICTIONARY = {};
|
||||||
|
|
@ -40,13 +40,17 @@ module.exports = function(context) {
|
||||||
let options = node.arguments[2];
|
let options = node.arguments[2];
|
||||||
if (options) {
|
if (options) {
|
||||||
if (options.type == "ObjectExpression") {
|
if (options.type == "ObjectExpression") {
|
||||||
if (options.properties.some(p => p.key.name == "once" &&
|
if (
|
||||||
p.value.value === true)) {
|
options.properties.some(
|
||||||
|
p => p.key.name == "once" && p.value.value === true
|
||||||
|
)
|
||||||
|
) {
|
||||||
// No point in adding listeners using the 'once' option.
|
// No point in adding listeners using the 'once' option.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
capture = options.properties.some(p => p.key.name == "capture" &&
|
capture = options.properties.some(
|
||||||
p.value.value === true);
|
p => p.key.name == "capture" && p.value.value === true
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
capture = options.value;
|
capture = options.value;
|
||||||
}
|
}
|
||||||
|
|
@ -64,8 +68,9 @@ module.exports = function(context) {
|
||||||
let options = node.arguments[2];
|
let options = node.arguments[2];
|
||||||
if (options) {
|
if (options) {
|
||||||
if (options.type == "ObjectExpression") {
|
if (options.type == "ObjectExpression") {
|
||||||
capture = options.properties.some(p => p.key.name == "capture" &&
|
capture = options.properties.some(
|
||||||
p.value.value === true);
|
p => p.key.name == "capture" && p.value.value === true
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
capture = options.value;
|
capture = options.value;
|
||||||
}
|
}
|
||||||
|
|
@ -93,9 +98,11 @@ module.exports = function(context) {
|
||||||
function hasRemovedListener(addedListener) {
|
function hasRemovedListener(addedListener) {
|
||||||
for (var k = 0; k < removedListeners.length; k++) {
|
for (var k = 0; k < removedListeners.length; k++) {
|
||||||
var listener = removedListeners[k];
|
var listener = removedListeners[k];
|
||||||
if (DICTIONARY[addedListener.functionName] === listener.functionName &&
|
if (
|
||||||
addedListener.type === listener.type &&
|
DICTIONARY[addedListener.functionName] === listener.functionName &&
|
||||||
addedListener.useCapture === listener.useCapture) {
|
addedListener.type === listener.type &&
|
||||||
|
addedListener.useCapture === listener.useCapture
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,12 +133,14 @@ module.exports = function(context) {
|
||||||
|
|
||||||
"Program:exit": function() {
|
"Program:exit": function() {
|
||||||
getUnbalancedListeners().forEach(function(listener) {
|
getUnbalancedListeners().forEach(function(listener) {
|
||||||
context.report(listener.node,
|
context.report(
|
||||||
|
listener.node,
|
||||||
"No corresponding '{{functionName}}({{type}})' was found.",
|
"No corresponding '{{functionName}}({{type}})' was found.",
|
||||||
{
|
{
|
||||||
functionName: DICTIONARY[listener.functionName],
|
functionName: DICTIONARY[listener.functionName],
|
||||||
type: listener.type,
|
type: listener.type,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,17 @@ module.exports = {
|
||||||
IfStatement(node) {
|
IfStatement(node) {
|
||||||
if (node.parent.type !== "IfStatement") {
|
if (node.parent.type !== "IfStatement") {
|
||||||
let types = new Set();
|
let types = new Set();
|
||||||
for (let currentNode = node; currentNode; currentNode = currentNode.alternate) {
|
for (
|
||||||
|
let currentNode = node;
|
||||||
|
currentNode;
|
||||||
|
currentNode = currentNode.alternate
|
||||||
|
) {
|
||||||
let type = currentNode.consequent.type;
|
let type = currentNode.consequent.type;
|
||||||
types.add(type == "BlockStatement" ? "Block" : "NotBlock");
|
types.add(type == "BlockStatement" ? "Block" : "NotBlock");
|
||||||
if (currentNode.alternate && currentNode.alternate.type !== "IfStatement") {
|
if (
|
||||||
|
currentNode.alternate &&
|
||||||
|
currentNode.alternate.type !== "IfStatement"
|
||||||
|
) {
|
||||||
type = currentNode.alternate.type;
|
type = currentNode.alternate.type;
|
||||||
types.add(type == "BlockStatement" ? "Block" : "NotBlock");
|
types.add(type == "BlockStatement" ? "Block" : "NotBlock");
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,16 @@ module.exports = function(context) {
|
||||||
relativePath = relativePath.split(path.sep).join("/");
|
relativePath = relativePath.split(path.sep).join("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browserWindowEnv.browserjsScripts &&
|
if (
|
||||||
browserWindowEnv.browserjsScripts.includes(relativePath)) {
|
browserWindowEnv.browserjsScripts &&
|
||||||
|
browserWindowEnv.browserjsScripts.includes(relativePath)
|
||||||
|
) {
|
||||||
for (let global in browserWindowEnv.globals) {
|
for (let global in browserWindowEnv.globals) {
|
||||||
helpers.addVarToScope(global, context.getScope(),
|
helpers.addVarToScope(
|
||||||
browserWindowEnv.globals[global]);
|
global,
|
||||||
|
context.getScope(),
|
||||||
|
browserWindowEnv.globals[global]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,15 @@ module.exports = function(context) {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"CallExpression[callee.object.name='ContentTask'][callee.property.name='spawn']": function(node) {
|
"CallExpression[callee.object.name='ContentTask'][callee.property.name='spawn']": function(
|
||||||
|
node
|
||||||
|
) {
|
||||||
for (let global in frameScriptEnv.globals) {
|
for (let global in frameScriptEnv.globals) {
|
||||||
helpers.addVarToScope(global, context.getScope(),
|
helpers.addVarToScope(
|
||||||
frameScriptEnv.globals[global]);
|
global,
|
||||||
|
context.getScope(),
|
||||||
|
frameScriptEnv.globals[global]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,13 @@ module.exports = function(context) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
AssignmentExpression(node, parents) {
|
AssignmentExpression(node, parents) {
|
||||||
if (node.operator === "=" &&
|
if (
|
||||||
node.left.type === "MemberExpression" &&
|
node.operator === "=" &&
|
||||||
node.left.object.type === "ThisExpression" &&
|
node.left.type === "MemberExpression" &&
|
||||||
node.left.property.name === "EXPORTED_SYMBOLS" &&
|
node.left.object.type === "ThisExpression" &&
|
||||||
isGlobalScope()) {
|
node.left.property.name === "EXPORTED_SYMBOLS" &&
|
||||||
|
isGlobalScope()
|
||||||
|
) {
|
||||||
markArrayElementsAsUsed(context, node, node.right);
|
markArrayElementsAsUsed(context, node, node.right);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -58,15 +60,18 @@ module.exports = function(context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let item of node.declarations) {
|
for (let item of node.declarations) {
|
||||||
if (item.id &&
|
if (
|
||||||
item.id.type == "Identifier" &&
|
item.id &&
|
||||||
item.id.name === "EXPORTED_SYMBOLS") {
|
item.id.type == "Identifier" &&
|
||||||
|
item.id.name === "EXPORTED_SYMBOLS"
|
||||||
|
) {
|
||||||
if (node.kind === "let") {
|
if (node.kind === "let") {
|
||||||
// The use of 'let' isn't allowed as the lexical scope may die after
|
// The use of 'let' isn't allowed as the lexical scope may die after
|
||||||
// the script executes.
|
// the script executes.
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
message: "EXPORTED_SYMBOLS cannot be declared via `let`. Use `var` or `this.EXPORTED_SYMBOLS =`",
|
message:
|
||||||
|
"EXPORTED_SYMBOLS cannot be declared via `let`. Use `var` or `this.EXPORTED_SYMBOLS =`",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,7 @@ module.exports = function(context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function deHungarianize(name) {
|
function deHungarianize(name) {
|
||||||
return name.substring(1, 2).toLowerCase() +
|
return name.substring(1, 2).toLowerCase() + name.substring(2, name.length);
|
||||||
name.substring(2, name.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkFunction(node) {
|
function checkFunction(node) {
|
||||||
|
|
@ -35,10 +34,12 @@ module.exports = function(context) {
|
||||||
name: param.name,
|
name: param.name,
|
||||||
suggestion: deHungarianize(param.name),
|
suggestion: deHungarianize(param.name),
|
||||||
};
|
};
|
||||||
context.report(param,
|
context.report(
|
||||||
"Parameter '{{name}}' uses Hungarian Notation, " +
|
param,
|
||||||
"consider using '{{suggestion}}' instead.",
|
"Parameter '{{name}}' uses Hungarian Notation, " +
|
||||||
errorObj);
|
"consider using '{{suggestion}}' instead.",
|
||||||
|
errorObj
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -48,8 +49,8 @@ module.exports = function(context) {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"FunctionDeclaration": checkFunction,
|
FunctionDeclaration: checkFunction,
|
||||||
"ArrowFunctionExpression": checkFunction,
|
ArrowFunctionExpression: checkFunction,
|
||||||
"FunctionExpression": checkFunction,
|
FunctionExpression: checkFunction,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,7 @@
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
var helpers = require("../helpers");
|
var helpers = require("../helpers");
|
||||||
var testTypes = new Set([
|
var testTypes = new Set(["browser", "xpcshell"]);
|
||||||
"browser",
|
|
||||||
"xpcshell",
|
|
||||||
]);
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
meta: {
|
meta: {
|
||||||
|
|
@ -33,7 +30,7 @@ module.exports = {
|
||||||
|
|
||||||
create(context) {
|
create(context) {
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
// We don't want to run this on mochitest plain as it already
|
// We don't want to run this on mochitest plain as it already
|
||||||
// prevents flaky setTimeout at runtime. This check is built-in
|
// prevents flaky setTimeout at runtime. This check is built-in
|
||||||
// to the rule itself as sometimes other tests can live alongside
|
// to the rule itself as sometimes other tests can live alongside
|
||||||
|
|
@ -44,14 +41,15 @@ module.exports = {
|
||||||
|
|
||||||
let callee = node.callee;
|
let callee = node.callee;
|
||||||
if (callee.type === "MemberExpression") {
|
if (callee.type === "MemberExpression") {
|
||||||
if (callee.property.name !== "setTimeout" ||
|
if (
|
||||||
callee.object.name !== "window" ||
|
callee.property.name !== "setTimeout" ||
|
||||||
node.arguments.length < 2) {
|
callee.object.name !== "window" ||
|
||||||
|
node.arguments.length < 2
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (callee.type === "Identifier") {
|
} else if (callee.type === "Identifier") {
|
||||||
if (callee.name !== "setTimeout" ||
|
if (callee.name !== "setTimeout" || node.arguments.length < 2) {
|
||||||
node.arguments.length < 2) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -60,8 +58,11 @@ module.exports = {
|
||||||
|
|
||||||
let timeout = node.arguments[1];
|
let timeout = node.arguments[1];
|
||||||
if (timeout.type !== "Literal" || timeout.value > 0) {
|
if (timeout.type !== "Literal" || timeout.value > 0) {
|
||||||
context.report(node, "listen for events instead of setTimeout() " +
|
context.report(
|
||||||
"with arbitrary delay");
|
node,
|
||||||
|
"listen for events instead of setTimeout() " +
|
||||||
|
"with arbitrary delay"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,16 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"BinaryExpression": function(node) {
|
BinaryExpression(node) {
|
||||||
if (["==", "!="].includes(node.operator) &&
|
if (
|
||||||
(["true", "false"].includes(node.left.raw) ||
|
["==", "!="].includes(node.operator) &&
|
||||||
["true", "false"].includes(node.right.raw))) {
|
(["true", "false"].includes(node.left.raw) ||
|
||||||
context.report(node, "Don't compare for inexact equality against boolean literals");
|
["true", "false"].includes(node.right.raw))
|
||||||
|
) {
|
||||||
|
context.report(
|
||||||
|
node,
|
||||||
|
"Don't compare for inexact equality against boolean literals"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,17 +20,31 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"VariableDeclarator": function(node) {
|
VariableDeclarator(node) {
|
||||||
if (node.id.type == "Identifier" && componentsBlacklist.includes(node.id.name)) {
|
if (
|
||||||
context.report(node,
|
node.id.type == "Identifier" &&
|
||||||
`${node.id.name} is now defined in global scope, a separate definition is no longer necessary.`);
|
componentsBlacklist.includes(node.id.name)
|
||||||
|
) {
|
||||||
|
context.report(
|
||||||
|
node,
|
||||||
|
`${
|
||||||
|
node.id.name
|
||||||
|
} is now defined in global scope, a separate definition is no longer necessary.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.id.type == "ObjectPattern") {
|
if (node.id.type == "ObjectPattern") {
|
||||||
for (let property of node.id.properties) {
|
for (let property of node.id.properties) {
|
||||||
if (property.type == "Property" && componentsBlacklist.includes(property.value.name)) {
|
if (
|
||||||
context.report(node,
|
property.type == "Property" &&
|
||||||
`${property.value.name} is now defined in global scope, a separate definition is no longer necessary.`);
|
componentsBlacklist.includes(property.value.name)
|
||||||
|
) {
|
||||||
|
context.report(
|
||||||
|
node,
|
||||||
|
`${
|
||||||
|
property.value.name
|
||||||
|
} is now defined in global scope, a separate definition is no longer necessary.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,14 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
let callee = node.callee;
|
let callee = node.callee;
|
||||||
if (callee.type === "MemberExpression" &&
|
if (
|
||||||
callee.object.type === "Identifier" &&
|
callee.type === "MemberExpression" &&
|
||||||
callee.object.name === "Task") {
|
callee.object.type === "Identifier" &&
|
||||||
context.report({node, message: "Task.jsm is deprecated."});
|
callee.object.name === "Task"
|
||||||
|
) {
|
||||||
|
context.report({ node, message: "Task.jsm is deprecated." });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,10 @@
|
||||||
module.exports = function(context) {
|
module.exports = function(context) {
|
||||||
function getRangeAfterArgToEnd(argNumber, args) {
|
function getRangeAfterArgToEnd(argNumber, args) {
|
||||||
let sourceCode = context.getSourceCode();
|
let sourceCode = context.getSourceCode();
|
||||||
return [sourceCode.getTokenAfter(args[argNumber]).range[0],
|
return [
|
||||||
args[args.length - 1].range[1]];
|
sourceCode.getTokenAfter(args[argNumber]).range[0],
|
||||||
|
args[args.length - 1].range[1],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
@ -25,22 +27,29 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
let callee = node.callee;
|
let callee = node.callee;
|
||||||
if (callee.type !== "MemberExpression" ||
|
if (
|
||||||
callee.property.type !== "Identifier") {
|
callee.type !== "MemberExpression" ||
|
||||||
|
callee.property.type !== "Identifier"
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let isFalse = arg => arg.type === "Literal" && arg.value === false;
|
let isFalse = arg => arg.type === "Literal" && arg.value === false;
|
||||||
let isFalsy = arg => arg.type === "Literal" && !arg.value;
|
let isFalsy = arg => arg.type === "Literal" && !arg.value;
|
||||||
let isBool = arg => arg.type === "Literal" && (arg.value === false ||
|
let isBool = arg =>
|
||||||
arg.value === true);
|
arg.type === "Literal" && (arg.value === false || arg.value === true);
|
||||||
let name = callee.property.name;
|
let name = callee.property.name;
|
||||||
let args = node.arguments;
|
let args = node.arguments;
|
||||||
|
|
||||||
if (["addEventListener", "removeEventListener", "addObserver"]
|
if (
|
||||||
.includes(name) && args.length === 3 && isFalse(args[2])) {
|
["addEventListener", "removeEventListener", "addObserver"].includes(
|
||||||
|
name
|
||||||
|
) &&
|
||||||
|
args.length === 3 &&
|
||||||
|
isFalse(args[2])
|
||||||
|
) {
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
fix: fixer => {
|
fix: fixer => {
|
||||||
|
|
@ -80,8 +89,7 @@ module.exports = function(context) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name === "notifyObservers" && args.length === 3 &&
|
if (name === "notifyObservers" && args.length === 3 && isFalsy(args[2])) {
|
||||||
isFalsy(args[2])) {
|
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
fix: fixer => {
|
fix: fixer => {
|
||||||
|
|
@ -91,8 +99,11 @@ module.exports = function(context) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name === "getComputedStyle" && args.length === 2 &&
|
if (
|
||||||
isFalsy(args[1])) {
|
name === "getComputedStyle" &&
|
||||||
|
args.length === 2 &&
|
||||||
|
isFalsy(args[1])
|
||||||
|
) {
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
fix: fixer => {
|
fix: fixer => {
|
||||||
|
|
@ -102,8 +113,11 @@ module.exports = function(context) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name === "newURI" && args.length > 1 &&
|
if (
|
||||||
isFalsy(args[args.length - 1])) {
|
name === "newURI" &&
|
||||||
|
args.length > 1 &&
|
||||||
|
isFalsy(args[args.length - 1])
|
||||||
|
) {
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
fix: fixer => {
|
fix: fixer => {
|
||||||
|
|
@ -111,7 +125,9 @@ module.exports = function(context) {
|
||||||
return fixer.removeRange(getRangeAfterArgToEnd(0, args));
|
return fixer.removeRange(getRangeAfterArgToEnd(0, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
return fixer.removeRange(getRangeAfterArgToEnd(args.length - 2, args));
|
return fixer.removeRange(
|
||||||
|
getRangeAfterArgToEnd(args.length - 2, args)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
message: "newURI's last parameters are optional.",
|
message: "newURI's last parameters are optional.",
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -19,37 +19,45 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
let callee = node.callee;
|
let callee = node.callee;
|
||||||
if (callee.type !== "MemberExpression" ||
|
if (
|
||||||
callee.property.type !== "Identifier" ||
|
callee.type !== "MemberExpression" ||
|
||||||
callee.property.name !== "addEventListener" ||
|
callee.property.type !== "Identifier" ||
|
||||||
node.arguments.length == 4) {
|
callee.property.name !== "addEventListener" ||
|
||||||
|
node.arguments.length == 4
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let listener = node.arguments[1];
|
let listener = node.arguments[1];
|
||||||
if (!listener ||
|
if (
|
||||||
listener.type != "FunctionExpression" ||
|
!listener ||
|
||||||
!listener.body ||
|
listener.type != "FunctionExpression" ||
|
||||||
listener.body.type != "BlockStatement" ||
|
!listener.body ||
|
||||||
!listener.body.body.length ||
|
listener.body.type != "BlockStatement" ||
|
||||||
listener.body.body[0].type != "ExpressionStatement" ||
|
!listener.body.body.length ||
|
||||||
listener.body.body[0].expression.type != "CallExpression") {
|
listener.body.body[0].type != "ExpressionStatement" ||
|
||||||
|
listener.body.body[0].expression.type != "CallExpression"
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let call = listener.body.body[0].expression;
|
let call = listener.body.body[0].expression;
|
||||||
if (call.callee.type == "MemberExpression" &&
|
if (
|
||||||
call.callee.property.type == "Identifier" &&
|
call.callee.type == "MemberExpression" &&
|
||||||
call.callee.property.name == "removeEventListener" &&
|
call.callee.property.type == "Identifier" &&
|
||||||
((call.arguments[0].type == "Literal" &&
|
call.callee.property.name == "removeEventListener" &&
|
||||||
call.arguments[0].value == node.arguments[0].value) ||
|
((call.arguments[0].type == "Literal" &&
|
||||||
(call.arguments[0].type == "Identifier" &&
|
call.arguments[0].value == node.arguments[0].value) ||
|
||||||
call.arguments[0].name == node.arguments[0].name))) {
|
(call.arguments[0].type == "Identifier" &&
|
||||||
context.report(call,
|
call.arguments[0].name == node.arguments[0].name))
|
||||||
"use {once: true} instead of removeEventListener as " +
|
) {
|
||||||
"the first instruction of the listener");
|
context.report(
|
||||||
|
call,
|
||||||
|
"use {once: true} instead of removeEventListener as " +
|
||||||
|
"the first instruction of the listener"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,14 @@ module.exports = function(context) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"Program > FunctionDeclaration": function(node) {
|
"Program > FunctionDeclaration": function(node) {
|
||||||
if (node.id.name === "run_test" &&
|
if (
|
||||||
node.body.type === "BlockStatement" &&
|
node.id.name === "run_test" &&
|
||||||
node.body.body.length === 1 &&
|
node.body.type === "BlockStatement" &&
|
||||||
node.body.body[0].type === "ExpressionStatement" &&
|
node.body.body.length === 1 &&
|
||||||
node.body.body[0].expression.type === "CallExpression" &&
|
node.body.body[0].type === "ExpressionStatement" &&
|
||||||
node.body.body[0].expression.callee.name === "run_next_test") {
|
node.body.body[0].expression.type === "CallExpression" &&
|
||||||
|
node.body.body[0].expression.callee.name === "run_next_test"
|
||||||
|
) {
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
fix: fixer => {
|
fix: fixer => {
|
||||||
|
|
@ -51,7 +53,7 @@ module.exports = function(context) {
|
||||||
return fixer.removeRange([
|
return fixer.removeRange([
|
||||||
// If there's no startNode, we fall back to zero, i.e. start of
|
// If there's no startNode, we fall back to zero, i.e. start of
|
||||||
// file.
|
// file.
|
||||||
startNode ? (startNode.end + 1) : 0,
|
startNode ? startNode.end + 1 : 0,
|
||||||
// We know the function is a block and it'll end with }. Normally
|
// We know the function is a block and it'll end with }. Normally
|
||||||
// there's a new line after that, so just advance past it. This
|
// there's a new line after that, so just advance past it. This
|
||||||
// may be slightly not dodgy in some cases, but covers the existing
|
// may be slightly not dodgy in some cases, but covers the existing
|
||||||
|
|
@ -59,7 +61,8 @@ module.exports = function(context) {
|
||||||
node.end + 1,
|
node.end + 1,
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
message: "Useless run_test function - only contains run_next_test; whole function can be removed",
|
message:
|
||||||
|
"Useless run_test function - only contains run_next_test; whole function can be removed",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const privilegedGlobals = Object.keys(require("../environments/privileged.js").globals);
|
const privilegedGlobals = Object.keys(
|
||||||
|
require("../environments/privileged.js").globals
|
||||||
|
);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Rule Definition
|
// Rule Definition
|
||||||
|
|
@ -18,35 +20,40 @@ module.exports = {
|
||||||
meta: {
|
meta: {
|
||||||
messages: {
|
messages: {
|
||||||
unexpectedCall: "Unexpected call to Cu.importGlobalProperties",
|
unexpectedCall: "Unexpected call to Cu.importGlobalProperties",
|
||||||
unexpectedCallWebIdl: "Unnecessary call to Cu.importGlobalProperties (webidl names are automatically imported)",
|
unexpectedCallWebIdl:
|
||||||
|
"Unnecessary call to Cu.importGlobalProperties (webidl names are automatically imported)",
|
||||||
},
|
},
|
||||||
schema: [{
|
schema: [
|
||||||
// XXX Better name?
|
{
|
||||||
"enum": ["everything", "allownonwebidl"],
|
// XXX Better name?
|
||||||
}],
|
enum: ["everything", "allownonwebidl"],
|
||||||
|
},
|
||||||
|
],
|
||||||
type: "problem",
|
type: "problem",
|
||||||
},
|
},
|
||||||
|
|
||||||
create(context) {
|
create(context) {
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
if (node.callee.type !== "MemberExpression") {
|
if (node.callee.type !== "MemberExpression") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let memexp = node.callee;
|
let memexp = node.callee;
|
||||||
if (memexp.object.type === "Identifier" &&
|
if (
|
||||||
// Only Cu, not Components.utils; see bug 1230369.
|
memexp.object.type === "Identifier" &&
|
||||||
memexp.object.name === "Cu" &&
|
// Only Cu, not Components.utils; see bug 1230369.
|
||||||
memexp.property.type === "Identifier" &&
|
memexp.object.name === "Cu" &&
|
||||||
memexp.property.name === "importGlobalProperties") {
|
memexp.property.type === "Identifier" &&
|
||||||
|
memexp.property.name === "importGlobalProperties"
|
||||||
|
) {
|
||||||
if (context.options.includes("allownonwebidl")) {
|
if (context.options.includes("allownonwebidl")) {
|
||||||
for (let element of node.arguments[0].elements) {
|
for (let element of node.arguments[0].elements) {
|
||||||
if (privilegedGlobals.includes(element.value)) {
|
if (privilegedGlobals.includes(element.value)) {
|
||||||
context.report({ node, messageId: "unexpectedCallWebIdl"});
|
context.report({ node, messageId: "unexpectedCallWebIdl" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
context.report({node, messageId: "unexpectedCall"});
|
context.report({ node, messageId: "unexpectedCall" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ module.exports = function(context) {
|
||||||
// Public
|
// Public
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
if (typeof(context.options[0]) !== "string") {
|
if (typeof context.options[0] !== "string") {
|
||||||
throw new Error("reject-some-requires expects a regexp");
|
throw new Error("reject-some-requires expects a regexp");
|
||||||
}
|
}
|
||||||
const RX = new RegExp(context.options[0]);
|
const RX = new RegExp(context.options[0]);
|
||||||
|
|
@ -29,17 +29,21 @@ module.exports = function(context) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
if (node.callee.type == "Identifier" &&
|
if (
|
||||||
node.callee.name == "require" &&
|
node.callee.type == "Identifier" &&
|
||||||
node.arguments.length == 1 &&
|
node.callee.name == "require" &&
|
||||||
node.arguments[0].type == "Literal") {
|
node.arguments.length == 1 &&
|
||||||
|
node.arguments[0].type == "Literal"
|
||||||
|
) {
|
||||||
checkPath(node, node.arguments[0].value);
|
checkPath(node, node.arguments[0].value);
|
||||||
} else if (node.callee.type == "MemberExpression" &&
|
} else if (
|
||||||
node.callee.property.type == "Identifier" &&
|
node.callee.type == "MemberExpression" &&
|
||||||
node.callee.property.name == "lazyRequireGetter" &&
|
node.callee.property.type == "Identifier" &&
|
||||||
node.arguments.length >= 3 &&
|
node.callee.property.name == "lazyRequireGetter" &&
|
||||||
node.arguments[2].type == "Literal") {
|
node.arguments.length >= 3 &&
|
||||||
|
node.arguments[2].type == "Literal"
|
||||||
|
) {
|
||||||
checkPath(node, node.arguments[2].value);
|
checkPath(node, node.arguments[2].value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,15 @@ module.exports = {
|
||||||
|
|
||||||
create(context) {
|
create(context) {
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
if (node.callee.type === "MemberExpression") {
|
if (node.callee.type === "MemberExpression") {
|
||||||
let memexp = node.callee;
|
let memexp = node.callee;
|
||||||
if (memexp.object.type === "Identifier" &&
|
if (
|
||||||
memexp.object.name === "Assert" &&
|
memexp.object.type === "Identifier" &&
|
||||||
memexp.property.type === "Identifier" &&
|
memexp.object.name === "Assert" &&
|
||||||
memexp.property.name === "rejects") {
|
memexp.property.type === "Identifier" &&
|
||||||
|
memexp.property.name === "rejects"
|
||||||
|
) {
|
||||||
// We have ourselves an Assert.rejects.
|
// We have ourselves an Assert.rejects.
|
||||||
|
|
||||||
if (node.parent.type !== "AwaitExpression") {
|
if (node.parent.type !== "AwaitExpression") {
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,19 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"MemberExpression": function(node) {
|
MemberExpression(node) {
|
||||||
if (node.object.type === "Identifier" &&
|
if (
|
||||||
node.object.name === "Components" &&
|
node.object.type === "Identifier" &&
|
||||||
node.property.type === "Identifier" &&
|
node.object.name === "Components" &&
|
||||||
Object.getOwnPropertyNames(componentsMap).includes(node.property.name)) {
|
node.property.type === "Identifier" &&
|
||||||
context.report(node,
|
Object.getOwnPropertyNames(componentsMap).includes(node.property.name)
|
||||||
`Use ${componentsMap[node.property.name]} rather than Components.${node.property.name}`);
|
) {
|
||||||
|
context.report(
|
||||||
|
node,
|
||||||
|
`Use ${componentsMap[node.property.name]} rather than Components.${
|
||||||
|
node.property.name
|
||||||
|
}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -18,17 +18,19 @@ function isIdentifier(node, id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMemberExpression(node, object, member) {
|
function isMemberExpression(node, object, member) {
|
||||||
return (node.type === "MemberExpression" &&
|
return (
|
||||||
isIdentifier(node.object, object) &&
|
node.type === "MemberExpression" &&
|
||||||
isIdentifier(node.property, member));
|
isIdentifier(node.object, object) &&
|
||||||
|
isIdentifier(node.property, member)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MSG_NO_JS_QUERY_INTERFACE = (
|
const MSG_NO_JS_QUERY_INTERFACE =
|
||||||
"Please use ChromeUtils.generateQI rather than manually creating " +
|
"Please use ChromeUtils.generateQI rather than manually creating " +
|
||||||
"JavaScript QueryInterface functions");
|
"JavaScript QueryInterface functions";
|
||||||
|
|
||||||
const MSG_NO_XPCOMUTILS_GENERATEQI = (
|
const MSG_NO_XPCOMUTILS_GENERATEQI =
|
||||||
"Please use ChromeUtils.generateQI instead of XPCOMUtils.generateQI");
|
"Please use ChromeUtils.generateQI instead of XPCOMUtils.generateQI";
|
||||||
|
|
||||||
function funcToGenerateQI(context, node) {
|
function funcToGenerateQI(context, node) {
|
||||||
const sourceCode = context.getSourceCode();
|
const sourceCode = context.getSourceCode();
|
||||||
|
|
@ -41,9 +43,10 @@ function funcToGenerateQI(context, node) {
|
||||||
interfaces.push(match[1] || match[2]);
|
interfaces.push(match[1] || match[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ifaces = interfaces.filter(iface => iface != "nsISupports")
|
let ifaces = interfaces
|
||||||
.map(iface => JSON.stringify(iface))
|
.filter(iface => iface != "nsISupports")
|
||||||
.join(", ");
|
.map(iface => JSON.stringify(iface))
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
return `ChromeUtils.generateQI([${ifaces}])`;
|
return `ChromeUtils.generateQI([${ifaces}])`;
|
||||||
}
|
}
|
||||||
|
|
@ -55,8 +58,8 @@ module.exports = {
|
||||||
|
|
||||||
create(context) {
|
create(context) {
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
let {callee} = node;
|
let { callee } = node;
|
||||||
if (isMemberExpression(callee, "XPCOMUtils", "generateQI")) {
|
if (isMemberExpression(callee, "XPCOMUtils", "generateQI")) {
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
|
|
@ -68,8 +71,10 @@ module.exports = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"AssignmentExpression > MemberExpression[property.name='QueryInterface']": function(node) {
|
"AssignmentExpression > MemberExpression[property.name='QueryInterface']": function(
|
||||||
const {right} = node.parent;
|
node
|
||||||
|
) {
|
||||||
|
const { right } = node.parent;
|
||||||
if (right.type === "FunctionExpression") {
|
if (right.type === "FunctionExpression") {
|
||||||
context.report({
|
context.report({
|
||||||
node: node.parent,
|
node: node.parent,
|
||||||
|
|
@ -81,7 +86,9 @@ module.exports = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"Property[key.name='QueryInterface'][value.type='FunctionExpression']": function(node) {
|
"Property[key.name='QueryInterface'][value.type='FunctionExpression']": function(
|
||||||
|
node
|
||||||
|
) {
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
message: MSG_NO_JS_QUERY_INTERFACE,
|
message: MSG_NO_JS_QUERY_INTERFACE,
|
||||||
|
|
@ -94,4 +101,3 @@ module.exports = {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,22 +18,24 @@ function isIdentifier(node, id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMemberExpression(node, object, member) {
|
function isMemberExpression(node, object, member) {
|
||||||
return (node.type === "MemberExpression" &&
|
return (
|
||||||
isIdentifier(node.object, object) &&
|
node.type === "MemberExpression" &&
|
||||||
isIdentifier(node.property, member));
|
isIdentifier(node.object, object) &&
|
||||||
|
isIdentifier(node.property, member)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
meta: {
|
meta: {
|
||||||
schema: [
|
schema: [
|
||||||
{
|
{
|
||||||
"type": "object",
|
type: "object",
|
||||||
"properties": {
|
properties: {
|
||||||
"allowCu": {
|
allowCu: {
|
||||||
"type": "boolean",
|
type: "boolean",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
additionalProperties: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
fixable: "code",
|
fixable: "code",
|
||||||
|
|
@ -41,18 +43,20 @@ module.exports = {
|
||||||
|
|
||||||
create(context) {
|
create(context) {
|
||||||
return {
|
return {
|
||||||
"CallExpression": function(node) {
|
CallExpression(node) {
|
||||||
if (node.callee.type !== "MemberExpression") {
|
if (node.callee.type !== "MemberExpression") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let {allowCu} = context.options[0] || {};
|
let { allowCu } = context.options[0] || {};
|
||||||
let {callee} = node;
|
let { callee } = node;
|
||||||
|
|
||||||
// Is the expression starting with `Cu` or `Components.utils`?
|
// Is the expression starting with `Cu` or `Components.utils`?
|
||||||
if (((!allowCu && isIdentifier(callee.object, "Cu")) ||
|
if (
|
||||||
isMemberExpression(callee.object, "Components", "utils")) &&
|
((!allowCu && isIdentifier(callee.object, "Cu")) ||
|
||||||
isIdentifier(callee.property, "import")) {
|
isMemberExpression(callee.object, "Components", "utils")) &&
|
||||||
|
isIdentifier(callee.property, "import")
|
||||||
|
) {
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
message: "Please use ChromeUtils.import instead of Cu.import",
|
message: "Please use ChromeUtils.import instead of Cu.import",
|
||||||
|
|
@ -62,14 +66,20 @@ module.exports = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMemberExpression(callee, "XPCOMUtils", "defineLazyModuleGetter") &&
|
if (
|
||||||
node.arguments.length < 4) {
|
isMemberExpression(callee, "XPCOMUtils", "defineLazyModuleGetter") &&
|
||||||
|
node.arguments.length < 4
|
||||||
|
) {
|
||||||
context.report({
|
context.report({
|
||||||
node,
|
node,
|
||||||
message: ("Please use ChromeUtils.defineModuleGetter instead of " +
|
message:
|
||||||
"XPCOMUtils.defineLazyModuleGetter"),
|
"Please use ChromeUtils.defineModuleGetter instead of " +
|
||||||
|
"XPCOMUtils.defineLazyModuleGetter",
|
||||||
fix(fixer) {
|
fix(fixer) {
|
||||||
return fixer.replaceText(callee, "ChromeUtils.defineModuleGetter");
|
return fixer.replaceText(
|
||||||
|
callee,
|
||||||
|
"ChromeUtils.defineModuleGetter"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,21 +19,22 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"TryStatement": function(node) {
|
TryStatement(node) {
|
||||||
let types = ["Bool", "Char", "Float", "Int"];
|
let types = ["Bool", "Char", "Float", "Int"];
|
||||||
let methods = types.map(type => "get" + type + "Pref");
|
let methods = types.map(type => "get" + type + "Pref");
|
||||||
if (node.block.type != "BlockStatement" ||
|
if (node.block.type != "BlockStatement" || node.block.body.length != 1) {
|
||||||
node.block.body.length != 1) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let firstStm = node.block.body[0];
|
let firstStm = node.block.body[0];
|
||||||
if (firstStm.type != "ExpressionStatement" ||
|
if (
|
||||||
firstStm.expression.type != "AssignmentExpression" ||
|
firstStm.type != "ExpressionStatement" ||
|
||||||
firstStm.expression.right.type != "CallExpression" ||
|
firstStm.expression.type != "AssignmentExpression" ||
|
||||||
firstStm.expression.right.callee.type != "MemberExpression" ||
|
firstStm.expression.right.type != "CallExpression" ||
|
||||||
firstStm.expression.right.callee.property.type != "Identifier" ||
|
firstStm.expression.right.callee.type != "MemberExpression" ||
|
||||||
!methods.includes(firstStm.expression.right.callee.property.name)) {
|
firstStm.expression.right.callee.property.type != "Identifier" ||
|
||||||
|
!methods.includes(firstStm.expression.right.callee.property.name)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,22 +18,26 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"BinaryExpression": function(node) {
|
BinaryExpression(node) {
|
||||||
if (node.left.type != "CallExpression" ||
|
if (
|
||||||
node.left.callee.type != "MemberExpression" ||
|
node.left.type != "CallExpression" ||
|
||||||
node.left.callee.property.type != "Identifier" ||
|
node.left.callee.type != "MemberExpression" ||
|
||||||
node.left.callee.property.name != "indexOf") {
|
node.left.callee.property.type != "Identifier" ||
|
||||||
|
node.left.callee.property.name != "indexOf"
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((["!=", "!==", "==", "==="].includes(node.operator) &&
|
if (
|
||||||
node.right.type == "UnaryExpression" &&
|
(["!=", "!==", "==", "==="].includes(node.operator) &&
|
||||||
node.right.operator == "-" &&
|
node.right.type == "UnaryExpression" &&
|
||||||
node.right.argument.type == "Literal" &&
|
node.right.operator == "-" &&
|
||||||
node.right.argument.value == 1) ||
|
node.right.argument.type == "Literal" &&
|
||||||
([">=", "<"].includes(node.operator) &&
|
node.right.argument.value == 1) ||
|
||||||
node.right.type == "Literal" &&
|
([">=", "<"].includes(node.operator) &&
|
||||||
node.right.value == 0)) {
|
node.right.type == "Literal" &&
|
||||||
|
node.right.value == 0)
|
||||||
|
) {
|
||||||
context.report(node, "use .includes instead of .indexOf");
|
context.report(node, "use .includes instead of .indexOf");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -18,17 +18,21 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"MemberExpression": function(node) {
|
MemberExpression(node) {
|
||||||
if (node.property.type != "Identifier" ||
|
if (
|
||||||
node.property.name != "defaultView" ||
|
node.property.type != "Identifier" ||
|
||||||
node.object.type != "MemberExpression" ||
|
node.property.name != "defaultView" ||
|
||||||
node.object.property.type != "Identifier" ||
|
node.object.type != "MemberExpression" ||
|
||||||
node.object.property.name != "ownerDocument") {
|
node.object.property.type != "Identifier" ||
|
||||||
|
node.object.property.name != "ownerDocument"
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.report(node,
|
context.report(
|
||||||
"use .ownerGlobal instead of .ownerDocument.defaultView");
|
node,
|
||||||
|
"use .ownerGlobal instead of .ownerDocument.defaultView"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -18,21 +18,27 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"ExpressionStatement": function(node) {
|
ExpressionStatement(node) {
|
||||||
if (!node.expression ||
|
if (
|
||||||
node.expression.type != "CallExpression" ||
|
!node.expression ||
|
||||||
!node.expression.callee ||
|
node.expression.type != "CallExpression" ||
|
||||||
node.expression.callee.type != "MemberExpression" ||
|
!node.expression.callee ||
|
||||||
!node.expression.callee.property ||
|
node.expression.callee.type != "MemberExpression" ||
|
||||||
node.expression.callee.property.type != "Identifier" ||
|
!node.expression.callee.property ||
|
||||||
(node.expression.callee.property.name != "concat" &&
|
node.expression.callee.property.type != "Identifier" ||
|
||||||
node.expression.callee.property.name != "join" &&
|
(node.expression.callee.property.name != "concat" &&
|
||||||
node.expression.callee.property.name != "slice")) {
|
node.expression.callee.property.name != "join" &&
|
||||||
|
node.expression.callee.property.name != "slice")
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.report(node,
|
context.report(
|
||||||
`{Array/String}.${node.expression.callee.property.name} doesn't modify the instance in-place`);
|
node,
|
||||||
|
`{Array/String}.${
|
||||||
|
node.expression.callee.property.name
|
||||||
|
} doesn't modify the instance in-place`
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,16 @@ var servicesASTParser = {
|
||||||
identifiers: {},
|
identifiers: {},
|
||||||
// These interfaces are difficult/not possible to get via processing.
|
// These interfaces are difficult/not possible to get via processing.
|
||||||
result: {
|
result: {
|
||||||
"nsIPrefBranch": "prefs",
|
nsIPrefBranch: "prefs",
|
||||||
"nsIPrefService": "prefs",
|
nsIPrefService: "prefs",
|
||||||
"nsIXULRuntime": "appinfo",
|
nsIXULRuntime: "appinfo",
|
||||||
"nsIXULAppInfo": "appinfo",
|
nsIXULAppInfo: "appinfo",
|
||||||
"nsIDirectoryService": "dirsvc",
|
nsIDirectoryService: "dirsvc",
|
||||||
"nsIProperties": "dirsvc",
|
nsIProperties: "dirsvc",
|
||||||
"nsIIOService": "io",
|
nsIIOService: "io",
|
||||||
"nsISpeculativeConnect": "io",
|
nsISpeculativeConnect: "io",
|
||||||
"nsICookieManager": "cookies",
|
nsICookieManager: "cookies",
|
||||||
"nsIBlocklistService": "blocklist",
|
nsIBlocklistService: "blocklist",
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -39,10 +39,12 @@ var servicesASTParser = {
|
||||||
* with objects, and records the assumed interface definitions.
|
* with objects, and records the assumed interface definitions.
|
||||||
*/
|
*/
|
||||||
VariableDeclaration(node, parents) {
|
VariableDeclaration(node, parents) {
|
||||||
if (node.declarations.length === 1 &&
|
if (
|
||||||
node.declarations[0].id &&
|
node.declarations.length === 1 &&
|
||||||
helpers.getIsGlobalScope(parents) &&
|
node.declarations[0].id &&
|
||||||
node.declarations[0].init.type === "ObjectExpression") {
|
helpers.getIsGlobalScope(parents) &&
|
||||||
|
node.declarations[0].init.type === "ObjectExpression"
|
||||||
|
) {
|
||||||
let name = node.declarations[0].id.name;
|
let name = node.declarations[0].id.name;
|
||||||
let interfaces = {};
|
let interfaces = {};
|
||||||
|
|
||||||
|
|
@ -61,13 +63,16 @@ var servicesASTParser = {
|
||||||
* them to the identifier tables created by the VariableDeclaration calls.
|
* them to the identifier tables created by the VariableDeclaration calls.
|
||||||
*/
|
*/
|
||||||
AssignmentExpression(node, parents) {
|
AssignmentExpression(node, parents) {
|
||||||
if (node.left.type === "MemberExpression" &&
|
if (
|
||||||
node.right.type === "ArrayExpression" &&
|
node.left.type === "MemberExpression" &&
|
||||||
helpers.getIsGlobalScope(parents)) {
|
node.right.type === "ArrayExpression" &&
|
||||||
|
helpers.getIsGlobalScope(parents)
|
||||||
|
) {
|
||||||
let variableName = node.left.object.name;
|
let variableName = node.left.object.name;
|
||||||
if (variableName in this.identifiers) {
|
if (variableName in this.identifiers) {
|
||||||
let servicesPropName = node.left.property.name;
|
let servicesPropName = node.left.property.name;
|
||||||
this.identifiers[variableName][servicesPropName] = node.right.elements[1].value;
|
this.identifiers[variableName][servicesPropName] =
|
||||||
|
node.right.elements[1].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -78,11 +83,13 @@ var servicesASTParser = {
|
||||||
* Services.jsm is caching.
|
* Services.jsm is caching.
|
||||||
*/
|
*/
|
||||||
CallExpression(node) {
|
CallExpression(node) {
|
||||||
if (node.callee.object &&
|
if (
|
||||||
node.callee.object.name === "XPCOMUtils" &&
|
node.callee.object &&
|
||||||
node.callee.property &&
|
node.callee.object.name === "XPCOMUtils" &&
|
||||||
node.callee.property.name === "defineLazyServiceGetters" &&
|
node.callee.property &&
|
||||||
node.arguments.length >= 2) {
|
node.callee.property.name === "defineLazyServiceGetters" &&
|
||||||
|
node.arguments.length >= 2
|
||||||
|
) {
|
||||||
// The second argument has the getters name.
|
// The second argument has the getters name.
|
||||||
let gettersVarName = node.arguments[1].name;
|
let gettersVarName = node.arguments[1].name;
|
||||||
if (!(gettersVarName in this.identifiers)) {
|
if (!(gettersVarName in this.identifiers)) {
|
||||||
|
|
@ -97,7 +104,12 @@ var servicesASTParser = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function getInterfacesFromServicesFile() {
|
function getInterfacesFromServicesFile() {
|
||||||
let filePath = path.join(helpers.rootDir, "toolkit", "modules", "Services.jsm");
|
let filePath = path.join(
|
||||||
|
helpers.rootDir,
|
||||||
|
"toolkit",
|
||||||
|
"modules",
|
||||||
|
"Services.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
let content = fs.readFileSync(filePath, "utf8");
|
let content = fs.readFileSync(filePath, "utf8");
|
||||||
|
|
||||||
|
|
@ -120,9 +132,9 @@ function getInterfacesFromServicesFile() {
|
||||||
return servicesASTParser.result;
|
return servicesASTParser.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
let getServicesInterfaceMap = helpers.isMozillaCentralBased() ?
|
let getServicesInterfaceMap = helpers.isMozillaCentralBased()
|
||||||
getInterfacesFromServicesFile() :
|
? getInterfacesFromServicesFile()
|
||||||
helpers.getSavedRuleData("use-services.js");
|
: helpers.getSavedRuleData("use-services.js");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Rule Definition
|
// Rule Definition
|
||||||
|
|
@ -141,22 +153,27 @@ module.exports = function(context) {
|
||||||
},
|
},
|
||||||
|
|
||||||
CallExpression(node) {
|
CallExpression(node) {
|
||||||
if (!node.callee ||
|
if (
|
||||||
!node.callee.property ||
|
!node.callee ||
|
||||||
node.callee.property.type != "Identifier" ||
|
!node.callee.property ||
|
||||||
node.callee.property.name != "getService" ||
|
node.callee.property.type != "Identifier" ||
|
||||||
node.arguments.length != 1 ||
|
node.callee.property.name != "getService" ||
|
||||||
!node.arguments[0].property ||
|
node.arguments.length != 1 ||
|
||||||
node.arguments[0].property.type != "Identifier" ||
|
!node.arguments[0].property ||
|
||||||
!node.arguments[0].property.name ||
|
node.arguments[0].property.type != "Identifier" ||
|
||||||
!(node.arguments[0].property.name in getServicesInterfaceMap)) {
|
!node.arguments[0].property.name ||
|
||||||
|
!(node.arguments[0].property.name in getServicesInterfaceMap)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let serviceName = getServicesInterfaceMap[node.arguments[0].property.name];
|
let serviceName =
|
||||||
|
getServicesInterfaceMap[node.arguments[0].property.name];
|
||||||
|
|
||||||
context.report(node,
|
context.report(
|
||||||
`Use Services.${serviceName} rather than getService().`);
|
node,
|
||||||
|
`Use Services.${serviceName} rather than getService().`
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ module.exports = function(context) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"VariableDeclaration": function(node) {
|
VariableDeclaration(node) {
|
||||||
if (node.kind === "var") {
|
if (node.kind === "var") {
|
||||||
if (helpers.getIsGlobalScope(context.getAncestors())) {
|
if (helpers.getIsGlobalScope(context.getAncestors())) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,11 @@ function MozillaFormatter(runner) {
|
||||||
failures++;
|
failures++;
|
||||||
// Replace any newlines in the title.
|
// Replace any newlines in the title.
|
||||||
let title = test.title.replace(/\n/g, "|");
|
let title = test.title.replace(/\n/g, "|");
|
||||||
console.log(`TEST-UNEXPECTED-FAIL | ${path.basename(test.file)} | ${title} | ${err.message}`);
|
console.log(
|
||||||
|
`TEST-UNEXPECTED-FAIL | ${path.basename(test.file)} | ${title} | ${
|
||||||
|
err.message
|
||||||
|
}`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on("end", function() {
|
runner.on("end", function() {
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,32 @@ var fs = require("fs");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var helpers = require("../lib/helpers");
|
var helpers = require("../lib/helpers");
|
||||||
|
|
||||||
const eslintDir = path.join(helpers.rootDir,
|
const eslintDir = path.join(helpers.rootDir, "tools", "lint", "eslint");
|
||||||
"tools", "lint", "eslint");
|
|
||||||
|
|
||||||
const globalsFile = path.join(eslintDir, "eslint-plugin-mozilla",
|
const globalsFile = path.join(
|
||||||
"lib", "environments", "saved-globals.json");
|
eslintDir,
|
||||||
const rulesFile = path.join(eslintDir, "eslint-plugin-mozilla",
|
"eslint-plugin-mozilla",
|
||||||
"lib", "rules", "saved-rules-data.json");
|
"lib",
|
||||||
|
"environments",
|
||||||
|
"saved-globals.json"
|
||||||
|
);
|
||||||
|
const rulesFile = path.join(
|
||||||
|
eslintDir,
|
||||||
|
"eslint-plugin-mozilla",
|
||||||
|
"lib",
|
||||||
|
"rules",
|
||||||
|
"saved-rules-data.json"
|
||||||
|
);
|
||||||
|
|
||||||
console.log("Copying modules.json");
|
console.log("Copying modules.json");
|
||||||
|
|
||||||
const modulesFile = path.join(eslintDir, "modules.json");
|
const modulesFile = path.join(eslintDir, "modules.json");
|
||||||
const shipModulesFile = path.join(eslintDir, "eslint-plugin-mozilla", "lib",
|
const shipModulesFile = path.join(
|
||||||
"modules.json");
|
eslintDir,
|
||||||
|
"eslint-plugin-mozilla",
|
||||||
|
"lib",
|
||||||
|
"modules.json"
|
||||||
|
);
|
||||||
|
|
||||||
fs.writeFileSync(shipModulesFile, fs.readFileSync(modulesFile));
|
fs.writeFileSync(shipModulesFile, fs.readFileSync(modulesFile));
|
||||||
|
|
||||||
|
|
@ -31,26 +44,30 @@ console.log("Generating globals file");
|
||||||
// Export the environments.
|
// Export the environments.
|
||||||
let environmentGlobals = require("../lib/index.js").environments;
|
let environmentGlobals = require("../lib/index.js").environments;
|
||||||
|
|
||||||
return fs.writeFile(globalsFile, JSON.stringify({environments: environmentGlobals}), err => {
|
return fs.writeFile(
|
||||||
if (err) {
|
globalsFile,
|
||||||
console.error(err);
|
JSON.stringify({ environments: environmentGlobals }),
|
||||||
process.exit(1);
|
err => {
|
||||||
}
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
console.log("Globals file generation complete");
|
|
||||||
|
|
||||||
console.log("Creating rules data file");
|
|
||||||
// Also export data for the use-services.js rule
|
|
||||||
let rulesData = {
|
|
||||||
"use-services.js": require("../lib/rules/use-services.js")().getServicesInterfaceMap(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return fs.writeFile(rulesFile, JSON.stringify({rulesData}), err1 => {
|
|
||||||
if (err1) {
|
|
||||||
console.error(err1);
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Globals file generation complete");
|
console.log("Globals file generation complete");
|
||||||
});
|
|
||||||
});
|
console.log("Creating rules data file");
|
||||||
|
// Also export data for the use-services.js rule
|
||||||
|
let rulesData = {
|
||||||
|
"use-services.js": require("../lib/rules/use-services.js")().getServicesInterfaceMap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return fs.writeFile(rulesFile, JSON.stringify({ rulesData }), err1 => {
|
||||||
|
if (err1) {
|
||||||
|
console.error(err1);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Globals file generation complete");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function invalidCode(code, type, message) {
|
function invalidCode(code, type, message) {
|
||||||
return {code, errors: [{message, type}]};
|
return { code, errors: [{ message, type }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("avoid-Date-timing", rule, {
|
ruleTester.run("avoid-Date-timing", rule, {
|
||||||
|
|
@ -28,12 +28,15 @@ ruleTester.run("avoid-Date-timing", rule, {
|
||||||
"Date.UTC(2017, 7);",
|
"Date.UTC(2017, 7);",
|
||||||
],
|
],
|
||||||
invalid: [
|
invalid: [
|
||||||
invalidCode("Date.now();", "CallExpression",
|
invalidCode(
|
||||||
"use performance.now() instead of Date.now() " +
|
"Date.now();",
|
||||||
"for timing measurements"),
|
"CallExpression",
|
||||||
invalidCode("new Date();", "NewExpression",
|
"use performance.now() instead of Date.now() " + "for timing measurements"
|
||||||
"use performance.now() instead of new Date() " +
|
),
|
||||||
"for timing measurements"),
|
invalidCode(
|
||||||
|
"new Date();",
|
||||||
|
"NewExpression",
|
||||||
|
"use performance.now() instead of new Date() " + "for timing measurements"
|
||||||
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,11 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
|
|
||||||
function invalidCode(code, message) {
|
function invalidCode(code, message) {
|
||||||
if (!message) {
|
if (!message) {
|
||||||
message = "use element.remove() instead of " +
|
message =
|
||||||
"element.parentNode.removeChild(element)";
|
"use element.remove() instead of " +
|
||||||
|
"element.parentNode.removeChild(element)";
|
||||||
}
|
}
|
||||||
return {code, errors: [{message, type: "CallExpression"}]};
|
return { code, errors: [{ message, type: "CallExpression" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("avoid-removeChild", rule, {
|
ruleTester.run("avoid-removeChild", rule, {
|
||||||
|
|
@ -36,8 +37,10 @@ ruleTester.run("avoid-removeChild", rule, {
|
||||||
invalidCode("elt.parentNode.parentNode.removeChild(elt.parentNode);"),
|
invalidCode("elt.parentNode.parentNode.removeChild(elt.parentNode);"),
|
||||||
invalidCode("$(e).parentNode.removeChild($(e));"),
|
invalidCode("$(e).parentNode.removeChild($(e));"),
|
||||||
invalidCode("$('e').parentNode.removeChild($('e'));"),
|
invalidCode("$('e').parentNode.removeChild($('e'));"),
|
||||||
invalidCode("elt.removeChild(elt.firstChild);",
|
invalidCode(
|
||||||
"use element.firstChild.remove() instead of " +
|
"elt.removeChild(elt.firstChild);",
|
||||||
"element.removeChild(element.firstChild)"),
|
"use element.firstChild.remove() instead of " +
|
||||||
|
"element.removeChild(element.firstChild)"
|
||||||
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -19,61 +19,71 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
function error(code, message) {
|
function error(code, message) {
|
||||||
return {
|
return {
|
||||||
code,
|
code,
|
||||||
errors: [{message, type: "Identifier"}],
|
errors: [{ message, type: "Identifier" }],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("balanced-listeners", rule, {
|
ruleTester.run("balanced-listeners", rule, {
|
||||||
valid: [
|
valid: [
|
||||||
"elt.addEventListener('event', handler);" +
|
"elt.addEventListener('event', handler);" +
|
||||||
"elt.removeEventListener('event', handler);",
|
"elt.removeEventListener('event', handler);",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler, true);" +
|
"elt.addEventListener('event', handler, true);" +
|
||||||
"elt.removeEventListener('event', handler, true);",
|
"elt.removeEventListener('event', handler, true);",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler, false);" +
|
"elt.addEventListener('event', handler, false);" +
|
||||||
"elt.removeEventListener('event', handler, false);",
|
"elt.removeEventListener('event', handler, false);",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler);" +
|
"elt.addEventListener('event', handler);" +
|
||||||
"elt.removeEventListener('event', handler, false);",
|
"elt.removeEventListener('event', handler, false);",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler, false);" +
|
"elt.addEventListener('event', handler, false);" +
|
||||||
"elt.removeEventListener('event', handler);",
|
"elt.removeEventListener('event', handler);",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler, {capture: false});" +
|
"elt.addEventListener('event', handler, {capture: false});" +
|
||||||
"elt.removeEventListener('event', handler);",
|
"elt.removeEventListener('event', handler);",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler);" +
|
"elt.addEventListener('event', handler);" +
|
||||||
"elt.removeEventListener('event', handler, {capture: false});",
|
"elt.removeEventListener('event', handler, {capture: false});",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler, {capture: true});" +
|
"elt.addEventListener('event', handler, {capture: true});" +
|
||||||
"elt.removeEventListener('event', handler, true);",
|
"elt.removeEventListener('event', handler, true);",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler, true);" +
|
"elt.addEventListener('event', handler, true);" +
|
||||||
"elt.removeEventListener('event', handler, {capture: true});",
|
"elt.removeEventListener('event', handler, {capture: true});",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler, {once: true});",
|
"elt.addEventListener('event', handler, {once: true});",
|
||||||
|
|
||||||
"elt.addEventListener('event', handler, {once: true, capture: true});",
|
"elt.addEventListener('event', handler, {once: true, capture: true});",
|
||||||
],
|
],
|
||||||
invalid: [
|
invalid: [
|
||||||
error("elt.addEventListener('click', handler, false);",
|
error(
|
||||||
"No corresponding 'removeEventListener(click)' was found."),
|
"elt.addEventListener('click', handler, false);",
|
||||||
|
"No corresponding 'removeEventListener(click)' was found."
|
||||||
|
),
|
||||||
|
|
||||||
error("elt.addEventListener('click', handler, false);" +
|
error(
|
||||||
"elt.removeEventListener('click', handler, true);",
|
"elt.addEventListener('click', handler, false);" +
|
||||||
"No corresponding 'removeEventListener(click)' was found."),
|
"elt.removeEventListener('click', handler, true);",
|
||||||
|
"No corresponding 'removeEventListener(click)' was found."
|
||||||
|
),
|
||||||
|
|
||||||
error("elt.addEventListener('click', handler, {capture: false});" +
|
error(
|
||||||
"elt.removeEventListener('click', handler, true);",
|
"elt.addEventListener('click', handler, {capture: false});" +
|
||||||
"No corresponding 'removeEventListener(click)' was found."),
|
"elt.removeEventListener('click', handler, true);",
|
||||||
|
"No corresponding 'removeEventListener(click)' was found."
|
||||||
|
),
|
||||||
|
|
||||||
error("elt.addEventListener('click', handler, {capture: true});" +
|
error(
|
||||||
"elt.removeEventListener('click', handler);",
|
"elt.addEventListener('click', handler, {capture: true});" +
|
||||||
"No corresponding 'removeEventListener(click)' was found."),
|
"elt.removeEventListener('click', handler);",
|
||||||
|
"No corresponding 'removeEventListener(click)' was found."
|
||||||
|
),
|
||||||
|
|
||||||
error("elt.addEventListener('click', handler, true);" +
|
error(
|
||||||
"elt.removeEventListener('click', handler);",
|
"elt.addEventListener('click', handler, true);" +
|
||||||
"No corresponding 'removeEventListener(click)' was found."),
|
"elt.removeEventListener('click', handler);",
|
||||||
|
"No corresponding 'removeEventListener(click)' was found."
|
||||||
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 8 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function invalidCode(code) {
|
function invalidCode(code) {
|
||||||
return {code, errors: [{messageId: "consistentIfBracing"}]};
|
return { code, errors: [{ messageId: "consistentIfBracing" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("consistent-if-bracing", rule, {
|
ruleTester.run("consistent-if-bracing", rule, {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function invalidCode(code, type, message) {
|
function invalidCode(code, type, message) {
|
||||||
return {code, errors: [{message, type}]};
|
return { code, errors: [{ message, type }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("mark-exported-symbols-as-used", rule, {
|
ruleTester.run("mark-exported-symbols-as-used", rule, {
|
||||||
|
|
@ -26,11 +26,20 @@ ruleTester.run("mark-exported-symbols-as-used", rule, {
|
||||||
"this.EXPORTED_SYMBOLS = ['foo'];",
|
"this.EXPORTED_SYMBOLS = ['foo'];",
|
||||||
],
|
],
|
||||||
invalid: [
|
invalid: [
|
||||||
invalidCode("let EXPORTED_SYMBOLS = ['foo'];", "VariableDeclaration",
|
invalidCode(
|
||||||
"EXPORTED_SYMBOLS cannot be declared via `let`. Use `var` or `this.EXPORTED_SYMBOLS =`"),
|
"let EXPORTED_SYMBOLS = ['foo'];",
|
||||||
invalidCode("var EXPORTED_SYMBOLS = 'foo';", "VariableDeclaration",
|
"VariableDeclaration",
|
||||||
"Unexpected assignment of non-Array to EXPORTED_SYMBOLS"),
|
"EXPORTED_SYMBOLS cannot be declared via `let`. Use `var` or `this.EXPORTED_SYMBOLS =`"
|
||||||
invalidCode("this.EXPORTED_SYMBOLS = 'foo';", "AssignmentExpression",
|
),
|
||||||
"Unexpected assignment of non-Array to EXPORTED_SYMBOLS"),
|
invalidCode(
|
||||||
|
"var EXPORTED_SYMBOLS = 'foo';",
|
||||||
|
"VariableDeclaration",
|
||||||
|
"Unexpected assignment of non-Array to EXPORTED_SYMBOLS"
|
||||||
|
),
|
||||||
|
invalidCode(
|
||||||
|
"this.EXPORTED_SYMBOLS = 'foo';",
|
||||||
|
"AssignmentExpression",
|
||||||
|
"Unexpected assignment of non-Array to EXPORTED_SYMBOLS"
|
||||||
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,14 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function wrapCode(code, filename = "xpcshell/test_foo.js") {
|
function wrapCode(code, filename = "xpcshell/test_foo.js") {
|
||||||
return {code, filename};
|
return { code, filename };
|
||||||
}
|
}
|
||||||
|
|
||||||
function invalidCode(code) {
|
function invalidCode(code) {
|
||||||
let message = "listen for events instead of setTimeout() with arbitrary delay";
|
let message =
|
||||||
|
"listen for events instead of setTimeout() with arbitrary delay";
|
||||||
let obj = wrapCode(code);
|
let obj = wrapCode(code);
|
||||||
obj.errors = [{message, type: "CallExpression"}];
|
obj.errors = [{ message, type: "CallExpression" }];
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,4 +39,3 @@ ruleTester.run("no-arbitrary-setTimeout", rule, {
|
||||||
invalidCode("setTimeout(function() {}, timeout);"),
|
invalidCode("setTimeout(function() {}, timeout);"),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,13 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function callError(message) {
|
function callError(message) {
|
||||||
return [{message, type: "BinaryExpression"}];
|
return [{ message, type: "BinaryExpression" }];
|
||||||
}
|
}
|
||||||
|
|
||||||
const MESSAGE = "Don't compare for inexact equality against boolean literals";
|
const MESSAGE = "Don't compare for inexact equality against boolean literals";
|
||||||
|
|
||||||
ruleTester.run("no-compare-against-boolean-literals", rule, {
|
ruleTester.run("no-compare-against-boolean-literals", rule, {
|
||||||
valid: [
|
valid: [`if (!foo) {}`, `if (!!foo) {}`],
|
||||||
`if (!foo) {}`,
|
|
||||||
`if (!!foo) {}`,
|
|
||||||
],
|
|
||||||
invalid: [
|
invalid: [
|
||||||
{
|
{
|
||||||
code: `if (foo == true) {}`,
|
code: `if (foo == true) {}`,
|
||||||
|
|
@ -62,4 +59,3 @@ ruleTester.run("no-compare-against-boolean-literals", rule, {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,13 @@ function invalidCode(code, varNames) {
|
||||||
varNames = [varNames];
|
varNames = [varNames];
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
code, errors: varNames.map(name => [{
|
code,
|
||||||
message: `${name} is now defined in global scope, a separate definition is no longer necessary.`,
|
errors: varNames.map(name => [
|
||||||
type: "VariableDeclarator",
|
{
|
||||||
}]),
|
message: `${name} is now defined in global scope, a separate definition is no longer necessary.`,
|
||||||
|
type: "VariableDeclarator",
|
||||||
|
},
|
||||||
|
]),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +50,13 @@ ruleTester.run("no-define-cc-etc", rule, {
|
||||||
invalidCode("const {classes: Cc} = Components;", "Cc"),
|
invalidCode("const {classes: Cc} = Components;", "Cc"),
|
||||||
invalidCode("let {classes: Cc, manager: Cm} = Components", "Cc"),
|
invalidCode("let {classes: Cc, manager: Cm} = Components", "Cc"),
|
||||||
invalidCode("const Cu = Components.utils;", "Cu"),
|
invalidCode("const Cu = Components.utils;", "Cu"),
|
||||||
invalidCode("var Ci = Components.interfaces, Cc = Components.classes;", ["Ci", "Cc"]),
|
invalidCode("var Ci = Components.interfaces, Cc = Components.classes;", [
|
||||||
invalidCode("var {'interfaces': Ci, 'classes': Cc} = Components;", ["Ci", "Cc"]),
|
"Ci",
|
||||||
|
"Cc",
|
||||||
|
]),
|
||||||
|
invalidCode("var {'interfaces': Ci, 'classes': Cc} = Components;", [
|
||||||
|
"Ci",
|
||||||
|
"Cc",
|
||||||
|
]),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function callError(message) {
|
function callError(message) {
|
||||||
return [{message, type: "CallExpression"}];
|
return [{ message, type: "CallExpression" }];
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("no-useless-parameters", rule, {
|
ruleTester.run("no-useless-parameters", rule, {
|
||||||
|
|
@ -91,47 +91,47 @@ ruleTester.run("no-useless-parameters", rule, {
|
||||||
code: "elt.addEventListener('click', handler, false);",
|
code: "elt.addEventListener('click', handler, false);",
|
||||||
output: "elt.addEventListener('click', handler);",
|
output: "elt.addEventListener('click', handler);",
|
||||||
errors: callError(
|
errors: callError(
|
||||||
"addEventListener's third parameter can be omitted when it's false."),
|
"addEventListener's third parameter can be omitted when it's false."
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "elt.removeEventListener('click', handler, false);",
|
code: "elt.removeEventListener('click', handler, false);",
|
||||||
output: "elt.removeEventListener('click', handler);",
|
output: "elt.removeEventListener('click', handler);",
|
||||||
errors: callError(
|
errors: callError(
|
||||||
"removeEventListener's third parameter can be omitted when it's" +
|
"removeEventListener's third parameter can be omitted when it's" +
|
||||||
" false."),
|
" false."
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "Services.obs.addObserver(this, 'topic', false);",
|
code: "Services.obs.addObserver(this, 'topic', false);",
|
||||||
output: "Services.obs.addObserver(this, 'topic');",
|
output: "Services.obs.addObserver(this, 'topic');",
|
||||||
errors: callError(
|
errors: callError(
|
||||||
"addObserver's third parameter can be omitted when it's" +
|
"addObserver's third parameter can be omitted when it's" + " false."
|
||||||
" false."),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "Services.prefs.addObserver('branch', this, false);",
|
code: "Services.prefs.addObserver('branch', this, false);",
|
||||||
output: "Services.prefs.addObserver('branch', this);",
|
output: "Services.prefs.addObserver('branch', this);",
|
||||||
errors: callError(
|
errors: callError(
|
||||||
"addObserver's third parameter can be omitted when it's" +
|
"addObserver's third parameter can be omitted when it's" + " false."
|
||||||
" false."),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "array.appendElement(elt, false);",
|
code: "array.appendElement(elt, false);",
|
||||||
output: "array.appendElement(elt);",
|
output: "array.appendElement(elt);",
|
||||||
errors: callError(
|
errors: callError(
|
||||||
"appendElement's second parameter can be omitted when it's" +
|
"appendElement's second parameter can be omitted when it's" + " false."
|
||||||
" false."),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "Services.obs.notifyObservers(obj, 'topic', null);",
|
code: "Services.obs.notifyObservers(obj, 'topic', null);",
|
||||||
output: "Services.obs.notifyObservers(obj, 'topic');",
|
output: "Services.obs.notifyObservers(obj, 'topic');",
|
||||||
errors: callError(
|
errors: callError("notifyObservers's third parameter can be omitted."),
|
||||||
"notifyObservers's third parameter can be omitted."),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "Services.obs.notifyObservers(obj, 'topic', '');",
|
code: "Services.obs.notifyObservers(obj, 'topic', '');",
|
||||||
output: "Services.obs.notifyObservers(obj, 'topic');",
|
output: "Services.obs.notifyObservers(obj, 'topic');",
|
||||||
errors: callError(
|
errors: callError("notifyObservers's third parameter can be omitted."),
|
||||||
"notifyObservers's third parameter can be omitted."),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: "window.getComputedStyle(elt, null);",
|
code: "window.getComputedStyle(elt, null);",
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function invalidCode(code) {
|
function invalidCode(code) {
|
||||||
let message = "use {once: true} instead of removeEventListener " +
|
let message =
|
||||||
"as the first instruction of the listener";
|
"use {once: true} instead of removeEventListener " +
|
||||||
return {code, errors: [{message, type: "CallExpression"}]};
|
"as the first instruction of the listener";
|
||||||
|
return { code, errors: [{ message, type: "CallExpression" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("no-useless-removeEventListener", rule, {
|
ruleTester.run("no-useless-removeEventListener", rule, {
|
||||||
|
|
@ -34,53 +35,65 @@ ruleTester.run("no-useless-removeEventListener", rule, {
|
||||||
|
|
||||||
// Should not reject when removing a listener for another event.
|
// Should not reject when removing a listener for another event.
|
||||||
"elt.addEventListener('click', function listener() {" +
|
"elt.addEventListener('click', function listener() {" +
|
||||||
" elt.removeEventListener('keypress', listener);" +
|
" elt.removeEventListener('keypress', listener);" +
|
||||||
"});",
|
"});",
|
||||||
|
|
||||||
// Should not reject when there's another instruction before
|
// Should not reject when there's another instruction before
|
||||||
// removeEventListener.
|
// removeEventListener.
|
||||||
"elt.addEventListener('click', function listener() {" +
|
"elt.addEventListener('click', function listener() {" +
|
||||||
" elt.focus();" +
|
" elt.focus();" +
|
||||||
" elt.removeEventListener('click', listener);" +
|
" elt.removeEventListener('click', listener);" +
|
||||||
"});",
|
"});",
|
||||||
|
|
||||||
// Should not reject when wantsUntrusted is true.
|
// Should not reject when wantsUntrusted is true.
|
||||||
"elt.addEventListener('click', function listener() {" +
|
"elt.addEventListener('click', function listener() {" +
|
||||||
" elt.removeEventListener('click', listener);" +
|
" elt.removeEventListener('click', listener);" +
|
||||||
"}, false, true);",
|
"}, false, true);",
|
||||||
|
|
||||||
// Should not reject when there's a literal and a variable
|
// Should not reject when there's a literal and a variable
|
||||||
"elt.addEventListener('click', function listener() {" +
|
"elt.addEventListener('click', function listener() {" +
|
||||||
" elt.removeEventListener(eventName, listener);" +
|
" elt.removeEventListener(eventName, listener);" +
|
||||||
"});",
|
"});",
|
||||||
|
|
||||||
// Should not reject when there's 2 different variables
|
// Should not reject when there's 2 different variables
|
||||||
"elt.addEventListener(event1, function listener() {" +
|
"elt.addEventListener(event1, function listener() {" +
|
||||||
" elt.removeEventListener(event2, listener);" +
|
" elt.removeEventListener(event2, listener);" +
|
||||||
"});",
|
"});",
|
||||||
|
|
||||||
// Should not fail if this is a different type of event listener function.
|
// Should not fail if this is a different type of event listener function.
|
||||||
"myfunc.addEventListener(listener);",
|
"myfunc.addEventListener(listener);",
|
||||||
],
|
],
|
||||||
invalid: [
|
invalid: [
|
||||||
invalidCode("elt.addEventListener('click', function listener() {" +
|
invalidCode(
|
||||||
" elt.removeEventListener('click', listener);" +
|
"elt.addEventListener('click', function listener() {" +
|
||||||
"});"),
|
" elt.removeEventListener('click', listener);" +
|
||||||
invalidCode("elt.addEventListener('click', function listener() {" +
|
"});"
|
||||||
" elt.removeEventListener('click', listener, true);" +
|
),
|
||||||
"}, true);"),
|
invalidCode(
|
||||||
invalidCode("elt.addEventListener('click', function listener() {" +
|
"elt.addEventListener('click', function listener() {" +
|
||||||
" elt.removeEventListener('click', listener);" +
|
" elt.removeEventListener('click', listener, true);" +
|
||||||
"}, {once: true});"),
|
"}, true);"
|
||||||
invalidCode("elt.addEventListener('click', function listener() {" +
|
),
|
||||||
" /* Comment */" +
|
invalidCode(
|
||||||
" elt.removeEventListener('click', listener);" +
|
"elt.addEventListener('click', function listener() {" +
|
||||||
"});"),
|
" elt.removeEventListener('click', listener);" +
|
||||||
invalidCode("elt.addEventListener('click', function() {" +
|
"}, {once: true});"
|
||||||
" elt.removeEventListener('click', arguments.callee);" +
|
),
|
||||||
"});"),
|
invalidCode(
|
||||||
invalidCode("elt.addEventListener(eventName, function listener() {" +
|
"elt.addEventListener('click', function listener() {" +
|
||||||
" elt.removeEventListener(eventName, listener);" +
|
" /* Comment */" +
|
||||||
"});"),
|
" elt.removeEventListener('click', listener);" +
|
||||||
|
"});"
|
||||||
|
),
|
||||||
|
invalidCode(
|
||||||
|
"elt.addEventListener('click', function() {" +
|
||||||
|
" elt.removeEventListener('click', arguments.callee);" +
|
||||||
|
"});"
|
||||||
|
),
|
||||||
|
invalidCode(
|
||||||
|
"elt.addEventListener(eventName, function listener() {" +
|
||||||
|
" elt.removeEventListener(eventName, listener);" +
|
||||||
|
"});"
|
||||||
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
function invalidCode(code, output) {
|
function invalidCode(code, output) {
|
||||||
let message =
|
let message =
|
||||||
"Useless run_test function - only contains run_next_test; whole function can be removed";
|
"Useless run_test function - only contains run_next_test; whole function can be removed";
|
||||||
return {code, output, errors: [{message, type: "FunctionDeclaration"}]};
|
return { code, output, errors: [{ message, type: "FunctionDeclaration" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("no-useless-run-test", rule, {
|
ruleTester.run("no-useless-run-test", rule, {
|
||||||
|
|
@ -30,16 +30,17 @@ ruleTester.run("no-useless-run-test", rule, {
|
||||||
],
|
],
|
||||||
invalid: [
|
invalid: [
|
||||||
// Single-line case.
|
// Single-line case.
|
||||||
invalidCode(
|
invalidCode("function run_test() { run_next_test(); }", ""),
|
||||||
"function run_test() { run_next_test(); }",
|
|
||||||
""),
|
|
||||||
// Multiple-line cases
|
// Multiple-line cases
|
||||||
invalidCode(`
|
invalidCode(
|
||||||
|
`
|
||||||
function run_test() {
|
function run_test() {
|
||||||
run_next_test();
|
run_next_test();
|
||||||
}`,
|
}`,
|
||||||
``),
|
``
|
||||||
invalidCode(`
|
),
|
||||||
|
invalidCode(
|
||||||
|
`
|
||||||
foo();
|
foo();
|
||||||
function run_test() {
|
function run_test() {
|
||||||
run_next_test();
|
run_next_test();
|
||||||
|
|
@ -47,8 +48,10 @@ function run_test() {
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
foo();
|
foo();
|
||||||
`),
|
`
|
||||||
invalidCode(`
|
),
|
||||||
|
invalidCode(
|
||||||
|
`
|
||||||
foo();
|
foo();
|
||||||
function run_test() {
|
function run_test() {
|
||||||
run_next_test();
|
run_next_test();
|
||||||
|
|
@ -58,8 +61,10 @@ bar();
|
||||||
`
|
`
|
||||||
foo();
|
foo();
|
||||||
bar();
|
bar();
|
||||||
`),
|
`
|
||||||
invalidCode(`
|
),
|
||||||
|
invalidCode(
|
||||||
|
`
|
||||||
foo();
|
foo();
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
|
|
@ -70,8 +75,10 @@ bar();`,
|
||||||
`
|
`
|
||||||
foo();
|
foo();
|
||||||
|
|
||||||
bar();`),
|
bar();`
|
||||||
invalidCode(`
|
),
|
||||||
|
invalidCode(
|
||||||
|
`
|
||||||
foo();
|
foo();
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
|
|
@ -86,8 +93,10 @@ foo();
|
||||||
|
|
||||||
// A comment
|
// A comment
|
||||||
bar();
|
bar();
|
||||||
`),
|
`
|
||||||
invalidCode(`
|
),
|
||||||
|
invalidCode(
|
||||||
|
`
|
||||||
foo();
|
foo();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -109,6 +118,7 @@ foo();
|
||||||
|
|
||||||
// A comment
|
// A comment
|
||||||
bar();
|
bar();
|
||||||
`),
|
`
|
||||||
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,23 +17,30 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 8 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
ruleTester.run("reject-importGlobalProperties", rule, {
|
ruleTester.run("reject-importGlobalProperties", rule, {
|
||||||
valid: [{
|
valid: [
|
||||||
code: "Cu.something();",
|
{
|
||||||
}, {
|
code: "Cu.something();",
|
||||||
options: ["allownonwebidl"],
|
},
|
||||||
code: "Cu.importGlobalProperties(['fetch'])",
|
{
|
||||||
}],
|
options: ["allownonwebidl"],
|
||||||
invalid: [{
|
code: "Cu.importGlobalProperties(['fetch'])",
|
||||||
code: "Cu.importGlobalProperties(['fetch'])",
|
},
|
||||||
options: ["everything"],
|
],
|
||||||
errors: [{ messageId: "unexpectedCall"}],
|
invalid: [
|
||||||
}, {
|
{
|
||||||
code: "Cu.importGlobalProperties(['TextEncoder'])",
|
code: "Cu.importGlobalProperties(['fetch'])",
|
||||||
options: ["everything"],
|
options: ["everything"],
|
||||||
errors: [{ messageId: "unexpectedCall"}],
|
errors: [{ messageId: "unexpectedCall" }],
|
||||||
}, {
|
},
|
||||||
code: "Cu.importGlobalProperties(['TextEncoder'])",
|
{
|
||||||
options: ["allownonwebidl"],
|
code: "Cu.importGlobalProperties(['TextEncoder'])",
|
||||||
errors: [{ messageId: "unexpectedCallWebIdl"}],
|
options: ["everything"],
|
||||||
}],
|
errors: [{ messageId: "unexpectedCall" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "Cu.importGlobalProperties(['TextEncoder'])",
|
||||||
|
options: ["allownonwebidl"],
|
||||||
|
errors: [{ messageId: "unexpectedCallWebIdl" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 8 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function invalidCode(code, messageId) {
|
function invalidCode(code, messageId) {
|
||||||
return {code, errors: [{messageId: "rejectRequiresAwait"}]};
|
return { code, errors: [{ messageId: "rejectRequiresAwait" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("reject-requires-await", rule, {
|
ruleTester.run("reject-requires-await", rule, {
|
||||||
|
|
|
||||||
|
|
@ -17,21 +17,39 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function invalidCode(code, originalName, newName) {
|
function invalidCode(code, originalName, newName) {
|
||||||
return {code, errors: [{
|
return {
|
||||||
message: `Use ${newName} rather than ${originalName}`,
|
code,
|
||||||
type: "MemberExpression",
|
errors: [
|
||||||
}]};
|
{
|
||||||
|
message: `Use ${newName} rather than ${originalName}`,
|
||||||
|
type: "MemberExpression",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("use-cc-etc", rule, {
|
ruleTester.run("use-cc-etc", rule, {
|
||||||
valid: [
|
valid: ["Components.Constructor();", "let x = Components.foo;"],
|
||||||
"Components.Constructor();",
|
|
||||||
"let x = Components.foo;",
|
|
||||||
],
|
|
||||||
invalid: [
|
invalid: [
|
||||||
invalidCode("let foo = Components.classes['bar'];", "Components.classes", "Cc"),
|
invalidCode(
|
||||||
invalidCode("let bar = Components.interfaces.bar;", "Components.interfaces", "Ci"),
|
"let foo = Components.classes['bar'];",
|
||||||
invalidCode("Components.results.NS_ERROR_ILLEGAL_INPUT;", "Components.results", "Cr"),
|
"Components.classes",
|
||||||
invalidCode("Components.utils.reportError('fake');", "Components.utils", "Cu"),
|
"Cc"
|
||||||
|
),
|
||||||
|
invalidCode(
|
||||||
|
"let bar = Components.interfaces.bar;",
|
||||||
|
"Components.interfaces",
|
||||||
|
"Ci"
|
||||||
|
),
|
||||||
|
invalidCode(
|
||||||
|
"Components.results.NS_ERROR_ILLEGAL_INPUT;",
|
||||||
|
"Components.results",
|
||||||
|
"Cr"
|
||||||
|
),
|
||||||
|
invalidCode(
|
||||||
|
"Components.utils.reportError('fake');",
|
||||||
|
"Components.utils",
|
||||||
|
"Cu"
|
||||||
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,25 +17,27 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function callError(message) {
|
function callError(message) {
|
||||||
return [{message, type: "CallExpression"}];
|
return [{ message, type: "CallExpression" }];
|
||||||
}
|
}
|
||||||
function error(message, type) {
|
function error(message, type) {
|
||||||
return [{message, type}];
|
return [{ message, type }];
|
||||||
}
|
}
|
||||||
|
|
||||||
const MSG_NO_JS_QUERY_INTERFACE = (
|
const MSG_NO_JS_QUERY_INTERFACE =
|
||||||
"Please use ChromeUtils.generateQI rather than manually creating " +
|
"Please use ChromeUtils.generateQI rather than manually creating " +
|
||||||
"JavaScript QueryInterface functions");
|
"JavaScript QueryInterface functions";
|
||||||
|
|
||||||
const MSG_NO_XPCOMUTILS_GENERATEQI = (
|
const MSG_NO_XPCOMUTILS_GENERATEQI =
|
||||||
"Please use ChromeUtils.generateQI instead of XPCOMUtils.generateQI");
|
"Please use ChromeUtils.generateQI instead of XPCOMUtils.generateQI";
|
||||||
|
|
||||||
/* globals nsIFlug */
|
/* globals nsIFlug */
|
||||||
function QueryInterface(iid) {
|
function QueryInterface(iid) {
|
||||||
if (iid.equals(Ci.nsISupports) ||
|
if (
|
||||||
iid.equals(Ci.nsIMeh) ||
|
iid.equals(Ci.nsISupports) ||
|
||||||
iid.equals(nsIFlug) ||
|
iid.equals(Ci.nsIMeh) ||
|
||||||
iid.equals(Ci.amIFoo)) {
|
iid.equals(nsIFlug) ||
|
||||||
|
iid.equals(Ci.amIFoo)
|
||||||
|
) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||||
|
|
@ -63,7 +65,10 @@ ruleTester.run("use-chromeutils-generateqi", rule, {
|
||||||
errors: error(MSG_NO_JS_QUERY_INTERFACE, "Property"),
|
errors: error(MSG_NO_JS_QUERY_INTERFACE, "Property"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: `X.prototype = { ${String(QueryInterface).replace(/^function /, "")} };`,
|
code: `X.prototype = { ${String(QueryInterface).replace(
|
||||||
|
/^function /,
|
||||||
|
""
|
||||||
|
)} };`,
|
||||||
output: `X.prototype = { QueryInterface: ChromeUtils.generateQI(["nsIMeh", "nsIFlug", "amIFoo"]) };`,
|
output: `X.prototype = { QueryInterface: ChromeUtils.generateQI(["nsIMeh", "nsIFlug", "amIFoo"]) };`,
|
||||||
errors: error(MSG_NO_JS_QUERY_INTERFACE, "Property"),
|
errors: error(MSG_NO_JS_QUERY_INTERFACE, "Property"),
|
||||||
},
|
},
|
||||||
|
|
@ -74,4 +79,3 @@ ruleTester.run("use-chromeutils-generateqi", rule, {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,13 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function callError(message) {
|
function callError(message) {
|
||||||
return [{message, type: "CallExpression"}];
|
return [{ message, type: "CallExpression" }];
|
||||||
}
|
}
|
||||||
|
|
||||||
const MESSAGE_IMPORT = "Please use ChromeUtils.import instead of Cu.import";
|
const MESSAGE_IMPORT = "Please use ChromeUtils.import instead of Cu.import";
|
||||||
const MESSAGE_DEFINE = ("Please use ChromeUtils.defineModuleGetter instead of " +
|
const MESSAGE_DEFINE =
|
||||||
"XPCOMUtils.defineLazyModuleGetter");
|
"Please use ChromeUtils.defineModuleGetter instead of " +
|
||||||
|
"XPCOMUtils.defineLazyModuleGetter";
|
||||||
|
|
||||||
ruleTester.run("use-chromeutils-import", rule, {
|
ruleTester.run("use-chromeutils-import", rule, {
|
||||||
valid: [
|
valid: [
|
||||||
|
|
@ -37,7 +38,7 @@ ruleTester.run("use-chromeutils-import", rule, {
|
||||||
"resource://gre/modules/Service.jsm",
|
"resource://gre/modules/Service.jsm",
|
||||||
undefined, preServicesLambda);`,
|
undefined, preServicesLambda);`,
|
||||||
{
|
{
|
||||||
options: [{allowCu: true}],
|
options: [{ allowCu: true }],
|
||||||
code: `Cu.import("resource://gre/modules/Service.jsm");`,
|
code: `Cu.import("resource://gre/modules/Service.jsm");`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -63,7 +64,7 @@ ruleTester.run("use-chromeutils-import", rule, {
|
||||||
errors: callError(MESSAGE_IMPORT),
|
errors: callError(MESSAGE_IMPORT),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
options: [{allowCu: true}],
|
options: [{ allowCu: true }],
|
||||||
code: `Components.utils.import("resource://gre/modules/Services.jsm", this);`,
|
code: `Components.utils.import("resource://gre/modules/Services.jsm", this);`,
|
||||||
output: `ChromeUtils.import("resource://gre/modules/Services.jsm", this);`,
|
output: `ChromeUtils.import("resource://gre/modules/Services.jsm", this);`,
|
||||||
errors: callError(MESSAGE_IMPORT),
|
errors: callError(MESSAGE_IMPORT),
|
||||||
|
|
@ -77,4 +78,3 @@ ruleTester.run("use-chromeutils-import", rule, {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
|
|
||||||
function invalidCode(code) {
|
function invalidCode(code) {
|
||||||
let message = "provide a default value instead of using a try/catch block";
|
let message = "provide a default value instead of using a try/catch block";
|
||||||
return {code, errors: [{message, type: "TryStatement"}]};
|
return { code, errors: [{ message, type: "TryStatement" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
let types = ["Bool", "Char", "Float", "Int"];
|
let types = ["Bool", "Char", "Float", "Int"];
|
||||||
|
|
@ -28,12 +28,15 @@ ruleTester.run("use-default-preference-values", rule, {
|
||||||
valid: [].concat(
|
valid: [].concat(
|
||||||
methods.map(m => "blah = branch." + m + "('blah', true);"),
|
methods.map(m => "blah = branch." + m + "('blah', true);"),
|
||||||
methods.map(m => "blah = branch." + m + "('blah');"),
|
methods.map(m => "blah = branch." + m + "('blah');"),
|
||||||
methods.map(m => "try { canThrow();" +
|
methods.map(
|
||||||
" blah = branch." + m + "('blah'); } catch(e) {}")
|
m =>
|
||||||
|
"try { canThrow();" + " blah = branch." + m + "('blah'); } catch(e) {}"
|
||||||
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
invalid: [].concat(
|
invalid: [].concat(
|
||||||
methods.map(m =>
|
methods.map(m =>
|
||||||
invalidCode("try { blah = branch." + m + "('blah'); } catch(e) {}"))
|
invalidCode("try { blah = branch." + m + "('blah'); } catch(e) {}")
|
||||||
|
)
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
|
|
||||||
function invalidCode(code) {
|
function invalidCode(code) {
|
||||||
let message = "use .includes instead of .indexOf";
|
let message = "use .includes instead of .indexOf";
|
||||||
return {code, errors: [{message, type: "BinaryExpression"}]};
|
return { code, errors: [{ message, type: "BinaryExpression" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("use-includes-instead-of-indexOf", rule, {
|
ruleTester.run("use-includes-instead-of-indexOf", rule, {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
|
|
||||||
function invalidCode(code) {
|
function invalidCode(code) {
|
||||||
let message = "use .ownerGlobal instead of .ownerDocument.defaultView";
|
let message = "use .ownerGlobal instead of .ownerDocument.defaultView";
|
||||||
return {code, errors: [{message, type: "MemberExpression"}]};
|
return { code, errors: [{ message, type: "MemberExpression" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("use-ownerGlobal", rule, {
|
ruleTester.run("use-ownerGlobal", rule, {
|
||||||
|
|
@ -29,8 +29,7 @@ ruleTester.run("use-ownerGlobal", rule, {
|
||||||
],
|
],
|
||||||
invalid: [
|
invalid: [
|
||||||
invalidCode("aEvent.target.ownerDocument.defaultView;"),
|
invalidCode("aEvent.target.ownerDocument.defaultView;"),
|
||||||
invalidCode(
|
invalidCode("this.DOMPointNode.ownerDocument.defaultView.getSelection();"),
|
||||||
"this.DOMPointNode.ownerDocument.defaultView.getSelection();"),
|
|
||||||
invalidCode("windowToMessageManager(node.ownerDocument.defaultView);"),
|
invalidCode("windowToMessageManager(node.ownerDocument.defaultView);"),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
|
|
||||||
function invalidCode(code, methodName) {
|
function invalidCode(code, methodName) {
|
||||||
let message = `{Array/String}.${methodName} doesn't modify the instance in-place`;
|
let message = `{Array/String}.${methodName} doesn't modify the instance in-place`;
|
||||||
return {code, errors: [{message, type: "ExpressionStatement"}]};
|
return { code, errors: [{ message, type: "ExpressionStatement" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("use-returnValue", rule, {
|
ruleTester.run("use-returnValue", rule, {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
||||||
|
|
||||||
function invalidCode(code, name) {
|
function invalidCode(code, name) {
|
||||||
let message = `Use Services.${name} rather than getService().`;
|
let message = `Use Services.${name} rather than getService().`;
|
||||||
return {code, errors: [{message, type: "CallExpression"}]};
|
return { code, errors: [{ message, type: "CallExpression" }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleTester.run("use-services", rule, {
|
ruleTester.run("use-services", rule, {
|
||||||
|
|
@ -28,10 +28,13 @@ ruleTester.run("use-services", rule, {
|
||||||
"Services.wm.addListener()",
|
"Services.wm.addListener()",
|
||||||
],
|
],
|
||||||
invalid: [
|
invalid: [
|
||||||
invalidCode('Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);',
|
invalidCode(
|
||||||
"wm"),
|
'Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);',
|
||||||
|
"wm"
|
||||||
|
),
|
||||||
invalidCode(
|
invalidCode(
|
||||||
'Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup);',
|
'Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup);',
|
||||||
"startup"),
|
"startup"
|
||||||
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -11,53 +11,73 @@ add_task(async function test_profile_feature_jsallocations() {
|
||||||
if (!AppConstants.MOZ_GECKO_PROFILER) {
|
if (!AppConstants.MOZ_GECKO_PROFILER) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Assert.ok(!Services.profiler.IsActive(), "The profiler is not currently active");
|
Assert.ok(
|
||||||
|
!Services.profiler.IsActive(),
|
||||||
|
"The profiler is not currently active"
|
||||||
|
);
|
||||||
|
|
||||||
startProfiler({ features: ["threads", "js", "jsallocations"] });
|
startProfiler({ features: ["threads", "js", "jsallocations"] });
|
||||||
|
|
||||||
const url = BASE_URL + "do_work_500ms.html";
|
const url = BASE_URL + "do_work_500ms.html";
|
||||||
await BrowserTestUtils.withNewTab(url, async (contentBrowser) => {
|
await BrowserTestUtils.withNewTab(url, async contentBrowser => {
|
||||||
const contentPid = await ContentTask.spawn(contentBrowser, null,
|
const contentPid = await ContentTask.spawn(
|
||||||
() => Services.appinfo.processID);
|
contentBrowser,
|
||||||
|
null,
|
||||||
|
() => Services.appinfo.processID
|
||||||
|
);
|
||||||
|
|
||||||
// Wait 500ms so that the tab finishes executing.
|
// Wait 500ms so that the tab finishes executing.
|
||||||
await wait(500);
|
await wait(500);
|
||||||
|
|
||||||
// Check that we can get some allocations when the feature is turned on.
|
// Check that we can get some allocations when the feature is turned on.
|
||||||
{
|
{
|
||||||
const { parentThread, contentThread } = await stopProfilerAndGetThreads(contentPid);
|
const { parentThread, contentThread } = await stopProfilerAndGetThreads(
|
||||||
Assert.greater(getPayloadsOfType(parentThread, "JS allocation").length, 0,
|
contentPid
|
||||||
"Allocations were recorded for the parent process' main thread when the " +
|
);
|
||||||
"JS Allocation feature was turned on.");
|
Assert.greater(
|
||||||
Assert.greater(getPayloadsOfType(contentThread, "JS allocation").length, 0,
|
getPayloadsOfType(parentThread, "JS allocation").length,
|
||||||
"Allocations were recorded for the content process' main thread when the " +
|
0,
|
||||||
"JS Allocation feature was turned on.");
|
"Allocations were recorded for the parent process' main thread when the " +
|
||||||
}
|
"JS Allocation feature was turned on."
|
||||||
|
);
|
||||||
|
Assert.greater(
|
||||||
|
getPayloadsOfType(contentThread, "JS allocation").length,
|
||||||
|
0,
|
||||||
|
"Allocations were recorded for the content process' main thread when the " +
|
||||||
|
"JS Allocation feature was turned on."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Flush out any straggling allocation markers that may have not been collected
|
// Flush out any straggling allocation markers that may have not been collected
|
||||||
// yet by starting and stopping the profiler once.
|
// yet by starting and stopping the profiler once.
|
||||||
startProfiler({ features: ["threads", "js"] });
|
startProfiler({ features: ["threads", "js"] });
|
||||||
await stopProfilerAndGetThreads(contentPid);
|
await stopProfilerAndGetThreads(contentPid);
|
||||||
|
|
||||||
// Now reload the tab with a clean run.
|
// Now reload the tab with a clean run.
|
||||||
gBrowser.reload();
|
gBrowser.reload();
|
||||||
await wait(500);
|
await wait(500);
|
||||||
startProfiler({ features: ["threads", "js"] });
|
startProfiler({ features: ["threads", "js"] });
|
||||||
|
|
||||||
// Check that no allocations were recorded, and allocation tracking was correctly
|
// Check that no allocations were recorded, and allocation tracking was correctly
|
||||||
// turned off.
|
// turned off.
|
||||||
{
|
{
|
||||||
const { parentThread, contentThread } = await stopProfilerAndGetThreads(contentPid);
|
const { parentThread, contentThread } = await stopProfilerAndGetThreads(
|
||||||
Assert.equal(
|
contentPid
|
||||||
getPayloadsOfType(parentThread, "JS allocation").length, 0,
|
);
|
||||||
"No allocations were recorded for the parent processes' main thread when " +
|
Assert.equal(
|
||||||
"JS allocation was not turned on.");
|
getPayloadsOfType(parentThread, "JS allocation").length,
|
||||||
|
0,
|
||||||
|
"No allocations were recorded for the parent processes' main thread when " +
|
||||||
|
"JS allocation was not turned on."
|
||||||
|
);
|
||||||
|
|
||||||
Assert.equal(
|
Assert.equal(
|
||||||
getPayloadsOfType(contentThread, "JS allocation").length, 0,
|
getPayloadsOfType(contentThread, "JS allocation").length,
|
||||||
"No allocations were recorded for the content processes' main thread when " +
|
0,
|
||||||
"JS allocation was not turned on.");
|
"No allocations were recorded for the content processes' main thread when " +
|
||||||
}
|
"JS allocation was not turned on."
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -74,7 +94,7 @@ async function doAtLeastOnePeriodicSample() {
|
||||||
const sampleCount = await getProfileSampleCount();
|
const sampleCount = await getProfileSampleCount();
|
||||||
// Create an infinite loop until a sample has been collected.
|
// Create an infinite loop until a sample has been collected.
|
||||||
while (true) {
|
while (true) {
|
||||||
if (sampleCount < await getProfileSampleCount()) {
|
if (sampleCount < (await getProfileSampleCount())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +107,9 @@ async function stopProfilerAndGetThreads(contentPid) {
|
||||||
Services.profiler.StopProfiler();
|
Services.profiler.StopProfiler();
|
||||||
|
|
||||||
const parentThread = profile.threads[0];
|
const parentThread = profile.threads[0];
|
||||||
const contentProcess = profile.processes.find(p => p.threads[0].pid == contentPid);
|
const contentProcess = profile.processes.find(
|
||||||
|
p => p.threads[0].pid == contentPid
|
||||||
|
);
|
||||||
if (!contentProcess) {
|
if (!contentProcess) {
|
||||||
throw new Error("Could not find the content process.");
|
throw new Error("Could not find the content process.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@ add_task(async function test_profile_single_frame_page_info() {
|
||||||
|
|
||||||
let pageFound = false;
|
let pageFound = false;
|
||||||
// We need to find the correct content process for that tab.
|
// We need to find the correct content process for that tab.
|
||||||
let contentProcess = profile.processes.find(p => p.threads[0].pid == contentPid);
|
let contentProcess = profile.processes.find(
|
||||||
|
p => p.threads[0].pid == contentPid
|
||||||
|
);
|
||||||
for (const page of contentProcess.pages) {
|
for (const page of contentProcess.pages) {
|
||||||
if (page.url == url) {
|
if (page.url == url) {
|
||||||
Assert.equal(page.url, url);
|
Assert.equal(page.url, url);
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@ add_task(async function test_profile_pushstate_page_info() {
|
||||||
|
|
||||||
let foundPage = 0;
|
let foundPage = 0;
|
||||||
// We need to find the correct content process for that tab.
|
// We need to find the correct content process for that tab.
|
||||||
let contentProcess = profile.processes.find(p => p.threads[0].pid == contentPid);
|
let contentProcess = profile.processes.find(
|
||||||
|
p => p.threads[0].pid == contentPid
|
||||||
|
);
|
||||||
for (const page of contentProcess.pages) {
|
for (const page of contentProcess.pages) {
|
||||||
// Before pushState
|
// Before pushState
|
||||||
if (page.url == url) {
|
if (page.url == url) {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@ add_task(async function test_profile_replacestate_page_info() {
|
||||||
|
|
||||||
let foundPage = 0;
|
let foundPage = 0;
|
||||||
// We need to find the correct content process for that tab.
|
// We need to find the correct content process for that tab.
|
||||||
let contentProcess = profile.processes.find(p => p.threads[0].pid == contentPid);
|
let contentProcess = profile.processes.find(
|
||||||
|
p => p.threads[0].pid == contentPid
|
||||||
|
);
|
||||||
for (const page of contentProcess.pages) {
|
for (const page of contentProcess.pages) {
|
||||||
// Before replaceState
|
// Before replaceState
|
||||||
if (page.url == url) {
|
if (page.url == url) {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,9 @@ add_task(async function test_profile_multi_frame_page_info() {
|
||||||
|
|
||||||
let foundPage = 0;
|
let foundPage = 0;
|
||||||
// We need to find the correct content process for that tab.
|
// We need to find the correct content process for that tab.
|
||||||
let contentProcess = profile.processes.find(p => p.threads[0].pid == contentPid);
|
let contentProcess = profile.processes.find(
|
||||||
|
p => p.threads[0].pid == contentPid
|
||||||
|
);
|
||||||
for (const page of contentProcess.pages) {
|
for (const page of contentProcess.pages) {
|
||||||
// Parent page
|
// Parent page
|
||||||
if (page.url == url) {
|
if (page.url == url) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
const { BrowserTestUtils } = ChromeUtils.import(
|
||||||
const { BrowserTestUtils } = ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
|
"resource://testing-common/BrowserTestUtils.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
const BASE_URL = "http://example.com/browser/tools/profiler/tests/browser/";
|
const BASE_URL = "http://example.com/browser/tools/profiler/tests/browser/";
|
||||||
|
|
||||||
|
|
@ -44,7 +45,7 @@ function wait(time) {
|
||||||
* @return {Array} The payloads.
|
* @return {Array} The payloads.
|
||||||
*/
|
*/
|
||||||
function getPayloadsOfType(thread, type) {
|
function getPayloadsOfType(thread, type) {
|
||||||
const {markers} = thread;
|
const { markers } = thread;
|
||||||
const results = [];
|
const results = [];
|
||||||
for (const markerTuple of markers.data) {
|
for (const markerTuple of markers.data) {
|
||||||
const payload = markerTuple[markers.schema.data];
|
const payload = markerTuple[markers.schema.data];
|
||||||
|
|
|
||||||
|
|
@ -1,59 +1,63 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
const { Services } = ChromeUtils.import(
|
||||||
|
"resource://gre/modules/Services.jsm"
|
||||||
function startProfiler(settings) {
|
|
||||||
Services.profiler.StartProfiler(
|
|
||||||
settings.entries,
|
|
||||||
settings.interval,
|
|
||||||
settings.features,
|
|
||||||
settings.threads,
|
|
||||||
settings.duration
|
|
||||||
);
|
);
|
||||||
|
|
||||||
info("Profiler has started");
|
function startProfiler(settings) {
|
||||||
}
|
Services.profiler.StartProfiler(
|
||||||
|
settings.entries,
|
||||||
|
settings.interval,
|
||||||
|
settings.features,
|
||||||
|
settings.threads,
|
||||||
|
settings.duration
|
||||||
|
);
|
||||||
|
|
||||||
function getProfile() {
|
info("Profiler has started");
|
||||||
const profile = Services.profiler.getProfileData();
|
|
||||||
info("We got a profile, run the mochitest with `--keep-open true` to see the logged profile in the Web Console.");
|
|
||||||
|
|
||||||
// Run the mochitest with `--keep-open true` to see the logged profile in the
|
|
||||||
// Web console.
|
|
||||||
console.log(profile);
|
|
||||||
|
|
||||||
return profile;
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopProfiler() {
|
|
||||||
Services.profiler.StopProfiler();
|
|
||||||
info("Profiler has stopped");
|
|
||||||
}
|
|
||||||
|
|
||||||
function end(error) {
|
|
||||||
if (error) {
|
|
||||||
ok(false, `We got an error: ${error}`);
|
|
||||||
} else {
|
|
||||||
ok(true, "We ran the whole process");
|
|
||||||
}
|
}
|
||||||
SimpleTest.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runTest(settings, workload) {
|
function getProfile() {
|
||||||
SimpleTest.waitForExplicitFinish();
|
const profile = Services.profiler.getProfileData();
|
||||||
try {
|
info(
|
||||||
await startProfiler(settings);
|
"We got a profile, run the mochitest with `--keep-open true` to see the logged profile in the Web Console."
|
||||||
await workload();
|
);
|
||||||
await getProfile();
|
|
||||||
await stopProfiler();
|
// Run the mochitest with `--keep-open true` to see the logged profile in the
|
||||||
await end();
|
// Web console.
|
||||||
} catch (e) {
|
console.log(profile);
|
||||||
// By catching and handling the error, we're being nice to mochitest
|
|
||||||
// runners: instead of waiting for the timeout, we fail right away.
|
return profile;
|
||||||
await end(e);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
window.runTest = runTest;
|
function stopProfiler() {
|
||||||
|
Services.profiler.StopProfiler();
|
||||||
|
info("Profiler has stopped");
|
||||||
|
}
|
||||||
|
|
||||||
|
function end(error) {
|
||||||
|
if (error) {
|
||||||
|
ok(false, `We got an error: ${error}`);
|
||||||
|
} else {
|
||||||
|
ok(true, "We ran the whole process");
|
||||||
|
}
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runTest(settings, workload) {
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
try {
|
||||||
|
await startProfiler(settings);
|
||||||
|
await workload();
|
||||||
|
await getProfile();
|
||||||
|
await stopProfiler();
|
||||||
|
await end();
|
||||||
|
} catch (e) {
|
||||||
|
// By catching and handling the error, we're being nice to mochitest
|
||||||
|
// runners: instead of waiting for the timeout, we fail right away.
|
||||||
|
await end(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.runTest = runTest;
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* 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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
var {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
var { AppConstants } = ChromeUtils.import(
|
||||||
var {setTimeout} = ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
"resource://gre/modules/AppConstants.jsm"
|
||||||
|
);
|
||||||
|
var { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the payloads of a type recursively, including from all subprocesses.
|
* Get the payloads of a type recursively, including from all subprocesses.
|
||||||
|
|
@ -15,7 +17,7 @@ var {setTimeout} = ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
||||||
* @return {Array} The final payloads.
|
* @return {Array} The final payloads.
|
||||||
*/
|
*/
|
||||||
function getAllPayloadsOfType(profile, type, payloadTarget = []) {
|
function getAllPayloadsOfType(profile, type, payloadTarget = []) {
|
||||||
for (const {markers} of profile.threads) {
|
for (const { markers } of profile.threads) {
|
||||||
for (const markerTuple of markers.data) {
|
for (const markerTuple of markers.data) {
|
||||||
const payload = markerTuple[markers.schema.data];
|
const payload = markerTuple[markers.schema.data];
|
||||||
if (payload && payload.type === type) {
|
if (payload && payload.type === type) {
|
||||||
|
|
@ -31,7 +33,6 @@ function getAllPayloadsOfType(profile, type, payloadTarget = []) {
|
||||||
return payloadTarget;
|
return payloadTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a helper function be able to run `await wait(500)`. Unfortunately this
|
* This is a helper function be able to run `await wait(500)`. Unfortunately this
|
||||||
* is needed as the act of collecting functions relies on the periodic sampling of
|
* is needed as the act of collecting functions relies on the periodic sampling of
|
||||||
|
|
|
||||||
|
|
@ -1,77 +1,81 @@
|
||||||
// Check that asm.js code shows up on the stack.
|
// Check that asm.js code shows up on the stack.
|
||||||
function run_test() {
|
function run_test() {
|
||||||
// Just skip the test if the profiler component isn't present.
|
// Just skip the test if the profiler component isn't present.
|
||||||
if (!AppConstants.MOZ_GECKO_PROFILER) {
|
if (!AppConstants.MOZ_GECKO_PROFILER) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test assumes that it's starting on an empty profiler stack.
|
// This test assumes that it's starting on an empty profiler stack.
|
||||||
// (Note that the other profiler tests also assume the profiler
|
// (Note that the other profiler tests also assume the profiler
|
||||||
// isn't already started.)
|
// isn't already started.)
|
||||||
Assert.ok(!Services.profiler.IsActive());
|
Assert.ok(!Services.profiler.IsActive());
|
||||||
|
|
||||||
let jsFuns = Cu.getJSTestingFunctions();
|
let jsFuns = Cu.getJSTestingFunctions();
|
||||||
if (!jsFuns.isAsmJSCompilationAvailable())
|
if (!jsFuns.isAsmJSCompilationAvailable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ms = 10;
|
||||||
|
Services.profiler.StartProfiler(10000, ms, ["js"]);
|
||||||
|
|
||||||
|
let stack = null;
|
||||||
|
function ffi_function() {
|
||||||
|
var delayMS = 5;
|
||||||
|
while (1) {
|
||||||
|
let then = Date.now();
|
||||||
|
do {
|
||||||
|
// do nothing
|
||||||
|
} while (Date.now() - then < delayMS);
|
||||||
|
|
||||||
|
var thread0 = Services.profiler.getProfileData().threads[0];
|
||||||
|
|
||||||
|
if (delayMS > 30000) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const ms = 10;
|
delayMS *= 2;
|
||||||
Services.profiler.StartProfiler(10000, ms, ["js"]);
|
|
||||||
|
|
||||||
let stack = null;
|
if (thread0.samples.data.length == 0) {
|
||||||
function ffi_function() {
|
continue;
|
||||||
var delayMS = 5;
|
}
|
||||||
while (1) {
|
|
||||||
let then = Date.now();
|
|
||||||
do {
|
|
||||||
// do nothing
|
|
||||||
} while (Date.now() - then < delayMS);
|
|
||||||
|
|
||||||
var thread0 = Services.profiler.getProfileData().threads[0];
|
var lastSample = thread0.samples.data[thread0.samples.data.length - 1];
|
||||||
|
stack = String(getInflatedStackLocations(thread0, lastSample));
|
||||||
if (delayMS > 30000)
|
if (stack.includes("trampoline")) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
delayMS *= 2;
|
|
||||||
|
|
||||||
if (thread0.samples.data.length == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var lastSample = thread0.samples.data[thread0.samples.data.length - 1];
|
|
||||||
stack = String(getInflatedStackLocations(thread0, lastSample));
|
|
||||||
if (stack.includes("trampoline"))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function asmjs_module(global, ffis) {
|
function asmjs_module(global, ffis) {
|
||||||
"use asm";
|
"use asm";
|
||||||
var ffi = ffis.ffi;
|
var ffi = ffis.ffi;
|
||||||
function asmjs_function() {
|
function asmjs_function() {
|
||||||
ffi();
|
ffi();
|
||||||
}
|
|
||||||
return asmjs_function;
|
|
||||||
}
|
}
|
||||||
|
return asmjs_function;
|
||||||
|
}
|
||||||
|
|
||||||
Assert.ok(jsFuns.isAsmJSModule(asmjs_module));
|
Assert.ok(jsFuns.isAsmJSModule(asmjs_module));
|
||||||
|
|
||||||
var asmjs_function = asmjs_module(null, {ffi: ffi_function});
|
var asmjs_function = asmjs_module(null, { ffi: ffi_function });
|
||||||
Assert.ok(jsFuns.isAsmJSFunction(asmjs_function));
|
Assert.ok(jsFuns.isAsmJSFunction(asmjs_function));
|
||||||
|
|
||||||
asmjs_function();
|
asmjs_function();
|
||||||
|
|
||||||
Assert.notEqual(stack, null);
|
Assert.notEqual(stack, null);
|
||||||
|
|
||||||
var i1 = stack.indexOf("entry trampoline");
|
var i1 = stack.indexOf("entry trampoline");
|
||||||
Assert.ok(i1 !== -1);
|
Assert.ok(i1 !== -1);
|
||||||
var i2 = stack.indexOf("asmjs_function");
|
var i2 = stack.indexOf("asmjs_function");
|
||||||
Assert.ok(i2 !== -1);
|
Assert.ok(i2 !== -1);
|
||||||
var i3 = stack.indexOf("exit trampoline");
|
var i3 = stack.indexOf("exit trampoline");
|
||||||
Assert.ok(i3 !== -1);
|
Assert.ok(i3 !== -1);
|
||||||
var i4 = stack.indexOf("ffi_function");
|
var i4 = stack.indexOf("ffi_function");
|
||||||
Assert.ok(i4 !== -1);
|
Assert.ok(i4 !== -1);
|
||||||
Assert.ok(i1 < i2);
|
Assert.ok(i1 < i2);
|
||||||
Assert.ok(i2 < i3);
|
Assert.ok(i2 < i3);
|
||||||
Assert.ok(i3 < i4);
|
Assert.ok(i3 < i4);
|
||||||
|
|
||||||
Services.profiler.StopProfiler();
|
Services.profiler.StopProfiler();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,51 +2,54 @@
|
||||||
// usable by a native unwinder to resume unwinding after encountering
|
// usable by a native unwinder to resume unwinding after encountering
|
||||||
// JIT code, is pushed as expected.
|
// JIT code, is pushed as expected.
|
||||||
function run_test() {
|
function run_test() {
|
||||||
if (!AppConstants.MOZ_GECKO_PROFILER) {
|
if (!AppConstants.MOZ_GECKO_PROFILER) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test assumes that it's starting on an empty profiler stack.
|
// This test assumes that it's starting on an empty profiler stack.
|
||||||
// (Note that the other profiler tests also assume the profiler
|
// (Note that the other profiler tests also assume the profiler
|
||||||
// isn't already started.)
|
// isn't already started.)
|
||||||
Assert.ok(!Services.profiler.IsActive());
|
Assert.ok(!Services.profiler.IsActive());
|
||||||
|
|
||||||
const ms = 5;
|
const ms = 5;
|
||||||
Services.profiler.StartProfiler(10000, ms, ["js"]);
|
Services.profiler.StartProfiler(10000, ms, ["js"]);
|
||||||
|
|
||||||
function has_arbitrary_name_in_stack() {
|
function has_arbitrary_name_in_stack() {
|
||||||
// A frame for |arbitrary_name| has been pushed. Do a sequence of
|
// A frame for |arbitrary_name| has been pushed. Do a sequence of
|
||||||
// increasingly long spins until we get a sample.
|
// increasingly long spins until we get a sample.
|
||||||
var delayMS = 5;
|
var delayMS = 5;
|
||||||
while (1) {
|
while (1) {
|
||||||
info("loop: ms = " + delayMS);
|
info("loop: ms = " + delayMS);
|
||||||
const then = Date.now();
|
const then = Date.now();
|
||||||
do {
|
do {
|
||||||
let n = 10000;
|
let n = 10000;
|
||||||
while (--n); // OSR happens here
|
while (--n) {} // OSR happens here
|
||||||
// Spin in the hope of getting a sample.
|
// Spin in the hope of getting a sample.
|
||||||
} while (Date.now() - then < delayMS);
|
} while (Date.now() - then < delayMS);
|
||||||
let profile = Services.profiler.getProfileData().threads[0];
|
let profile = Services.profiler.getProfileData().threads[0];
|
||||||
|
|
||||||
// Go through all of the stacks, and search for this function name.
|
// Go through all of the stacks, and search for this function name.
|
||||||
for (const sample of profile.samples.data) {
|
for (const sample of profile.samples.data) {
|
||||||
const stack = getInflatedStackLocations(profile, sample);
|
const stack = getInflatedStackLocations(profile, sample);
|
||||||
info(`The following stack was found: ${stack}`);
|
info(`The following stack was found: ${stack}`);
|
||||||
for (var i = 0; i < stack.length; i++) {
|
for (var i = 0; i < stack.length; i++) {
|
||||||
if (stack[i].match(/arbitrary_name/)) {
|
if (stack[i].match(/arbitrary_name/)) {
|
||||||
// This JS sample was correctly found.
|
// This JS sample was correctly found.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Continue running this function with an increasingly long delay.
|
|
||||||
delayMS *= 2;
|
|
||||||
if (delayMS > 30000) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue running this function with an increasingly long delay.
|
||||||
|
delayMS *= 2;
|
||||||
|
if (delayMS > 30000) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Assert.ok(has_arbitrary_name_in_stack(), "A JS frame was found before the test timeout.");
|
}
|
||||||
Services.profiler.StopProfiler();
|
Assert.ok(
|
||||||
|
has_arbitrary_name_in_stack(),
|
||||||
|
"A JS frame was found before the test timeout."
|
||||||
|
);
|
||||||
|
Services.profiler.StopProfiler();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ function run_test() {
|
||||||
(function() {
|
(function() {
|
||||||
Services.profiler.StopProfiler();
|
Services.profiler.StopProfiler();
|
||||||
let n = 10000;
|
let n = 10000;
|
||||||
while (--n); // OSR happens here with the profiler disabled.
|
while (--n) {} // OSR happens here with the profiler disabled.
|
||||||
// An assertion will fail when this function returns, if the
|
// An assertion will fail when this function returns, if the
|
||||||
// profiler stack was misbalanced.
|
// profiler stack was misbalanced.
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ function run_test() {
|
||||||
(function() {
|
(function() {
|
||||||
Services.profiler.StartProfiler(100, 10, ["js"]);
|
Services.profiler.StartProfiler(100, 10, ["js"]);
|
||||||
let n = 10000;
|
let n = 10000;
|
||||||
while (--n); // OSR happens here with the profiler enabled.
|
while (--n) {} // OSR happens here with the profiler enabled.
|
||||||
// An assertion will fail when this function returns, if the
|
// An assertion will fail when this function returns, if the
|
||||||
// profiler stack was misbalanced.
|
// profiler stack was misbalanced.
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
const {FileUtils} = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
|
const { FileUtils } = ChromeUtils.import(
|
||||||
|
"resource://gre/modules/FileUtils.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that the IOInterposer is working correctly to capture main thread IO.
|
* Test that the IOInterposer is working correctly to capture main thread IO.
|
||||||
|
|
@ -21,10 +23,16 @@ add_task(async () => {
|
||||||
|
|
||||||
{
|
{
|
||||||
const filename = "profiler-mainthreadio-test-firstrun";
|
const filename = "profiler-mainthreadio-test-firstrun";
|
||||||
const payloads = await startProfilerAndgetFileIOPayloads(["mainthreadio"], filename);
|
const payloads = await startProfilerAndgetFileIOPayloads(
|
||||||
|
["mainthreadio"],
|
||||||
|
filename
|
||||||
|
);
|
||||||
|
|
||||||
greater(payloads.length, 0,
|
greater(
|
||||||
"FileIO markers were found when using the mainthreadio feature on the profiler.");
|
payloads.length,
|
||||||
|
0,
|
||||||
|
"FileIO markers were found when using the mainthreadio feature on the profiler."
|
||||||
|
);
|
||||||
|
|
||||||
// It would be better to check on the filename, but Linux does not currently include
|
// It would be better to check on the filename, but Linux does not currently include
|
||||||
// it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1533531
|
// it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1533531
|
||||||
|
|
@ -36,18 +44,27 @@ add_task(async () => {
|
||||||
const filename = "profiler-mainthreadio-test-no-instrumentation";
|
const filename = "profiler-mainthreadio-test-no-instrumentation";
|
||||||
const payloads = await startProfilerAndgetFileIOPayloads([], filename);
|
const payloads = await startProfilerAndgetFileIOPayloads([], filename);
|
||||||
|
|
||||||
equal(payloads.length, 0,
|
equal(
|
||||||
"No FileIO markers are found when the mainthreadio feature is not turned on " +
|
payloads.length,
|
||||||
"in the profiler.");
|
0,
|
||||||
|
"No FileIO markers are found when the mainthreadio feature is not turned on " +
|
||||||
|
"in the profiler."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const filename = "profiler-mainthreadio-test-secondrun";
|
const filename = "profiler-mainthreadio-test-secondrun";
|
||||||
const payloads = await startProfilerAndgetFileIOPayloads(["mainthreadio"], filename);
|
const payloads = await startProfilerAndgetFileIOPayloads(
|
||||||
|
["mainthreadio"],
|
||||||
|
filename
|
||||||
|
);
|
||||||
|
|
||||||
greater(payloads.length, 0,
|
greater(
|
||||||
"FileIO markers were found when re-starting the mainthreadio feature on the " +
|
payloads.length,
|
||||||
"profiler.");
|
0,
|
||||||
|
"FileIO markers were found when re-starting the mainthreadio feature on the " +
|
||||||
|
"profiler."
|
||||||
|
);
|
||||||
// It would be better to check on the filename, but Linux does not currently include
|
// It would be better to check on the filename, but Linux does not currently include
|
||||||
// it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1533531
|
// it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1533531
|
||||||
// ok(hasWritePayload(payloads, filename),
|
// ok(hasWritePayload(payloads, filename),
|
||||||
|
|
@ -67,14 +84,13 @@ async function startProfilerAndgetFileIOPayloads(features, filename) {
|
||||||
const threads = [];
|
const threads = [];
|
||||||
Services.profiler.StartProfiler(entries, interval, features, threads);
|
Services.profiler.StartProfiler(entries, interval, features, threads);
|
||||||
|
|
||||||
|
|
||||||
const file = FileUtils.getFile("TmpD", [filename]);
|
const file = FileUtils.getFile("TmpD", [filename]);
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"This test is triggering FileIO by writing to a file. However, the test found an " +
|
"This test is triggering FileIO by writing to a file. However, the test found an " +
|
||||||
"existing file at the location it was trying to write to. This could happen " +
|
"existing file at the location it was trying to write to. This could happen " +
|
||||||
"because a previous run of the test failed to clean up after itself. This test " +
|
"because a previous run of the test failed to clean up after itself. This test " +
|
||||||
" will now clean up that file before running the test again."
|
" will now clean up that file before running the test again."
|
||||||
);
|
);
|
||||||
file.remove(false);
|
file.remove(false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,11 @@
|
||||||
/* eslint-env webextensions */
|
/* eslint-env webextensions */
|
||||||
|
|
||||||
const Quitter = {
|
const Quitter = {
|
||||||
quit() { browser.runtime.sendMessage("quit"); },
|
quit() {
|
||||||
|
browser.runtime.sendMessage("quit");
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
window.wrappedJSObject.Quitter = cloneInto(Quitter, window, {cloneFunctions: true});
|
window.wrappedJSObject.Quitter = cloneInto(Quitter, window, {
|
||||||
|
cloneFunctions: true,
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,16 @@
|
||||||
|
|
||||||
/* globals ExtensionAPI */
|
/* globals ExtensionAPI */
|
||||||
|
|
||||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
this.quitter = class extends ExtensionAPI {
|
this.quitter = class extends ExtensionAPI {
|
||||||
getAPI(context) {
|
getAPI(context) {
|
||||||
return {
|
return {
|
||||||
quitter: {
|
quitter: {
|
||||||
async quit() {
|
async quit() {
|
||||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
let browserWindow = Services.wm.getMostRecentWindow(
|
||||||
|
"navigator:browser"
|
||||||
|
);
|
||||||
if (browserWindow && browserWindow.gBrowserInit) {
|
if (browserWindow && browserWindow.gBrowserInit) {
|
||||||
await browserWindow.gBrowserInit.idleTasksFinishedPromise;
|
await browserWindow.gBrowserInit.idleTasksFinishedPromise;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,17 @@ var apply = () => {
|
||||||
|
|
||||||
$(".filter:checked").each(function(index) {
|
$(".filter:checked").each(function(index) {
|
||||||
for (let kind of this.name.split(",")) {
|
for (let kind of this.name.split(",")) {
|
||||||
if (!(kinds.includes(kind)))
|
if (!kinds.includes(kind)) {
|
||||||
kinds.push(kind);
|
kinds.push(kind);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checkbox element values are generated by Section.get_context() in app.py
|
// Checkbox element values are generated by Section.get_context() in app.py
|
||||||
let attrs = JSON.parse(this.value);
|
let attrs = JSON.parse(this.value);
|
||||||
for (let attr in attrs) {
|
for (let attr in attrs) {
|
||||||
if (!(attr in filters))
|
if (!(attr in filters)) {
|
||||||
filters[attr] = [];
|
filters[attr] = [];
|
||||||
|
}
|
||||||
|
|
||||||
let values = attrs[attr];
|
let values = attrs[attr];
|
||||||
filters[attr] = filters[attr].concat(values);
|
filters[attr] = filters[attr].concat(values);
|
||||||
|
|
@ -35,24 +37,29 @@ var apply = () => {
|
||||||
});
|
});
|
||||||
updateLabels();
|
updateLabels();
|
||||||
|
|
||||||
if (Object.keys(filters).length == 0 || (Object.keys(filters).length == 1 && "build_type" in filters)) {
|
if (
|
||||||
|
Object.keys(filters).length == 0 ||
|
||||||
|
(Object.keys(filters).length == 1 && "build_type" in filters)
|
||||||
|
) {
|
||||||
selection.value = "";
|
selection.value = "";
|
||||||
count.innerHTML = "0 tasks selected";
|
count.innerHTML = "0 tasks selected";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskMatches = (label) => {
|
var taskMatches = label => {
|
||||||
let task = tasks[label];
|
let task = tasks[label];
|
||||||
|
|
||||||
// If no box for the given kind has been checked, this task is
|
// If no box for the given kind has been checked, this task is
|
||||||
// automatically not selected.
|
// automatically not selected.
|
||||||
if (!(kinds.includes(task.kind)))
|
if (!kinds.includes(task.kind)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (let attr in filters) {
|
for (let attr in filters) {
|
||||||
let values = filters[attr];
|
let values = filters[attr];
|
||||||
if (!(attr in task) || values.includes(task[attr]))
|
if (!(attr in task) || values.includes(task[attr])) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@ var lastChecked = {};
|
||||||
|
|
||||||
// implements shift+click
|
// implements shift+click
|
||||||
labels.click(function(e) {
|
labels.click(function(e) {
|
||||||
if (e.target.tagName === "INPUT")
|
if (e.target.tagName === "INPUT") {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let box = $("#" + this.htmlFor)[0];
|
let box = $("#" + this.htmlFor)[0];
|
||||||
let activeSection = $("div.tab-pane.active")[0].id;
|
let activeSection = $("div.tab-pane.active")[0].id;
|
||||||
|
|
@ -15,13 +16,16 @@ labels.click(function(e) {
|
||||||
let isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
|
let isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
|
||||||
|
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
if (isFirefox)
|
if (isFirefox) {
|
||||||
box.checked = !box.checked;
|
box.checked = !box.checked;
|
||||||
|
}
|
||||||
|
|
||||||
let start = boxes.index(box);
|
let start = boxes.index(box);
|
||||||
let end = boxes.index(lastChecked[activeSection]);
|
let end = boxes.index(lastChecked[activeSection]);
|
||||||
|
|
||||||
boxes.slice(Math.min(start, end), Math.max(start, end) + 1).prop("checked", box.checked);
|
boxes
|
||||||
|
.slice(Math.min(start, end), Math.max(start, end) + 1)
|
||||||
|
.prop("checked", box.checked);
|
||||||
apply();
|
apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue