--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -10,21 +10,21 @@ module.exports = {
"mozilla/avoid-nsISupportsString-preferences": "error",
"mozilla/import-browser-window-globals": "error",
"mozilla/import-globals": "warn",
"mozilla/no-import-into-var-and-global": "error",
"mozilla/no-useless-parameters": "error",
"mozilla/no-useless-removeEventListener": "error",
"mozilla/use-default-preference-values": "error",
"mozilla/use-ownerGlobal": "error",
-
// No (!foo in bar) or (!object instanceof Class)
"no-unsafe-negation": "error",
// No eval() and no strings in the first param of setTimeout or setInterval
"no-implied-eval": "error",
+ "no-eval": "error",
},
"env": {
"es6": true
},
"parserOptions": {
"ecmaVersion": 8,
},
};
--- a/browser/base/content/test/general/browser_aboutHome.js
+++ b/browser/base/content/test/general/browser_aboutHome.js
@@ -563,16 +563,17 @@ function* withSnippetsMap(setupFn, testF
}, function* (args) {
return new Promise(resolve => {
let document = content.document;
// We're not using Promise-based listeners, because they resolve asynchronously.
// The snippets test setup code relies on synchronous behaviour here.
document.addEventListener("AboutHomeLoadSnippets", function() {
let updateSnippets;
if (args.setupFnSource) {
+ // eslint-disable-next-line no-eval
updateSnippets = eval(`(() => (${args.setupFnSource}))()`);
}
content.wrappedJSObject.ensureSnippetsMapThen(snippetsMap => {
snippetsMap = Cu.waiveXrays(snippetsMap);
info("Got snippets map: " +
"{ last-update: " + snippetsMap.get("snippets-last-update") +
", cached-version: " + snippetsMap.get("snippets-cached-version") +
--- a/browser/base/content/test/general/browser_bug633691.js
+++ b/browser/base/content/test/general/browser_bug633691.js
@@ -11,18 +11,20 @@ add_task(function* test() {
function* ({ is_element_hidden_, is_hidden_ }) {
let loadError =
ContentTaskUtils.waitForEvent(this, "AboutNetErrorLoad", false, null, true);
let iframe = content.document.querySelector("iframe");
iframe.src = "https://expired.example.com/";
yield loadError;
+ /* eslint-disable no-eval */
let is_hidden = eval(`(() => ${is_hidden_})()`);
let is_element_hidden = eval(`(() => ${is_element_hidden_})()`);
+ /* eslint-enable no-eval */
let doc = content.document.getElementsByTagName("iframe")[0].contentDocument;
let aP = doc.getElementById("badCertAdvancedPanel");
ok(aP, "Advanced content should exist");
void is_hidden; // Quiet eslint warnings (actual use under is_element_hidden)
is_element_hidden(aP, "Advanced content should not be visible by default")
});
});
});
--- a/browser/base/content/test/newtab/head.js
+++ b/browser/base/content/test/newtab/head.js
@@ -138,16 +138,17 @@ add_task(function* setup() {
* @param aIndex index of cell
* @param aFn function to call in child process or tab.
* @returns result of calling the function.
*/
function performOnCell(aIndex, aFn) {
return ContentTask.spawn(gWindow.gBrowser.selectedBrowser,
{ index: aIndex, fn: aFn.toString() }, function* (args) {
let cell = content.gGrid.cells[args.index];
+ // eslint-disable-next-line no-eval
return eval(args.fn)(cell);
});
}
/**
* Allows to provide a list of links that is used to construct the grid.
* @param aLinksPattern the pattern (see below)
*
--- a/browser/components/preferences/in-content-old/tests/browser_subdialogs.js
+++ b/browser/components/preferences/in-content-old/tests/browser_subdialogs.js
@@ -19,16 +19,17 @@ function* open_subdialog_and_test_generi
let win = content.window;
let subdialog = win.gSubDialog;
subdialog.open(args.url, null, rv);
info("waiting for subdialog DOMFrameContentLoaded");
yield ContentTaskUtils.waitForEvent(win, "DOMFrameContentLoaded", true);
let result;
if (args.domcontentloadedFnStr) {
+ // eslint-disable-next-line no-eval
result = eval(args.domcontentloadedFnStr);
}
info("waiting for subdialog load");
yield ContentTaskUtils.waitForEvent(subdialog._frame, "load");
info("subdialog window is loaded");
let expectedStyleSheetURLs = subdialog._injectedStyleSheets.slice(0);
--- a/browser/components/preferences/in-content/tests/browser_subdialogs.js
+++ b/browser/components/preferences/in-content/tests/browser_subdialogs.js
@@ -19,16 +19,17 @@ function* open_subdialog_and_test_generi
let win = content.window;
let subdialog = win.gSubDialog;
subdialog.open(args.url, null, rv);
info("waiting for subdialog DOMFrameContentLoaded");
yield ContentTaskUtils.waitForEvent(win, "DOMFrameContentLoaded", true);
let result;
if (args.domcontentloadedFnStr) {
+ // eslint-disable-next-line no-eval
result = eval(args.domcontentloadedFnStr);
}
info("waiting for subdialog load");
yield ContentTaskUtils.waitForEvent(subdialog._frame, "load");
info("subdialog window is loaded");
let expectedStyleSheetURLs = subdialog._injectedStyleSheets.slice(0);
--- a/browser/components/sessionstore/test/browser_async_remove_tab.js
+++ b/browser/components/sessionstore/test/browser_async_remove_tab.js
@@ -33,16 +33,17 @@ function restoreClosedTabWithValue(rval)
}
function promiseNewLocationAndHistoryEntryReplaced(browser, snippet) {
return ContentTask.spawn(browser, snippet, function* (codeSnippet) {
let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
let shistory = webNavigation.sessionHistory;
// Evaluate the snippet that the changes the location.
+ // eslint-disable-next-line no-eval
eval(codeSnippet);
return new Promise(resolve => {
let listener = {
OnHistoryReplaceEntry() {
shistory.removeSHistoryListener(this);
resolve();
},
--- a/dom/indexedDB/test/test_error_events_abort_transactions.html
+++ b/dom/indexedDB/test/test_error_events_abort_transactions.html
@@ -9,16 +9,17 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript">
function runTest() {
SimpleTest.waitForExplicitFinish();
function messageListener(event) {
+ // eslint-disable-next-line no-eval
eval(event.data);
}
window.addEventListener("message", messageListener);
}
</script>
</head>
--- a/dom/indexedDB/test/test_event_propagation.html
+++ b/dom/indexedDB/test/test_event_propagation.html
@@ -9,16 +9,17 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript">
function runTest() {
SimpleTest.waitForExplicitFinish();
function messageListener(event) {
+ // eslint-disable-next-line no-eval
eval(event.data);
}
window.addEventListener("message", messageListener);
}
</script>
</head>
--- a/dom/indexedDB/test/test_exceptions_in_events.html
+++ b/dom/indexedDB/test/test_exceptions_in_events.html
@@ -9,16 +9,17 @@
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript">
function runTest() {
SimpleTest.waitForExplicitFinish();
function messageListener(event) {
+ // eslint-disable-next-line no-eval
eval(event.data);
}
window.addEventListener("message", messageListener);
}
</script>
</head>
--- a/dom/indexedDB/test/test_third_party.html
+++ b/dom/indexedDB/test/test_third_party.html
@@ -65,16 +65,17 @@
'set': [["network.cookie.cookieBehavior", testData[testIndex].cookieBehavior]]
}, () => {
iframe.src = testData[testIndex].host + iframe1Path;
});
// SpecialPowers.setIntPref("network.cookie.cookieBehavior", testData[testIndex].cookieBehavior);
}
function messageListener(event) {
+ // eslint-disable-next-line no-eval
let message = eval(event.data);
is(message.source, "iframe", "Good source");
is(message.result, testData[testIndex].expectedResult, "Good result");
if (testIndex < testData.length - 1) {
testIndex++;
setiframe();
--- a/dom/indexedDB/test/third_party_iframe1.html
+++ b/dom/indexedDB/test/third_party_iframe1.html
@@ -3,16 +3,17 @@
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Test</title>
<script type="text/javascript">
function messageListener(event) {
+ // eslint-disable-next-line no-eval
let message = eval(event.data);
if (message.source == "parent") {
document.getElementById("iframe2").src = message.href;
}
else if (message.source == "iframe") {
parent.postMessage(event.data, "*");
}
--- a/dom/indexedDB/test/unit/test_complex_keyPaths.js
+++ b/dom/indexedDB/test/unit/test_complex_keyPaths.js
@@ -134,16 +134,17 @@ function* testSteps()
request.onsuccess = grabEventAndContinueHandler;
yield undefined;
ok(true, "Successfully updated cursor" + test);
// Check that cursor.update throws as expected when key is changed
let newValue = cursor.value;
let destProp = Array.isArray(info.keyPath) ? info.keyPath[0] : info.keyPath;
if (destProp) {
+ // eslint-disable-next-line no-eval
eval("newValue." + destProp + " = 'newKeyValue'");
}
else {
newValue = 'newKeyValue';
}
let didThrow;
try {
cursor.update(newValue);
--- a/services/sync/tests/unit/test_utils_deepEquals.js
+++ b/services/sync/tests/unit/test_utils_deepEquals.js
@@ -1,16 +1,18 @@
_("Make sure Utils.deepEquals correctly finds items that are deeply equal");
Cu.import("resource://services-sync/util.js");
function run_test() {
let data = '[NaN, undefined, null, true, false, Infinity, 0, 1, "a", "b", {a: 1}, {a: "a"}, [{a: 1}], [{a: true}], {a: 1, b: 2}, [1, 2], [1, 2, 3]]';
_("Generating two copies of data:", data);
+ /* eslint-disable no-eval */
let d1 = eval(data);
let d2 = eval(data);
+ /* eslint-enable no-eval */
d1.forEach(function(a) {
_("Testing", a, typeof a, JSON.stringify([a]));
let numMatch = 0;
d2.forEach(function(b) {
if (Utils.deepEquals(a, b)) {
numMatch++;
--- a/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js
+++ b/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js
@@ -4,18 +4,20 @@
let global = this;
function run_test() {
var allTests = [];
for (var i = 0; i < tests.length; i++) {
// Generate two wrappers of each test function that invoke the original test with an
// appropriate privacy context.
+ /* eslint-disable no-eval */
var pub = eval("var f = function* " + tests[i].name + "() { yield tests[" + i + "](privateLoadContext); }; f");
var priv = eval("var f = function* " + tests[i].name + "_private() { yield tests[" + i + "](privateLoadContext); }; f");
+ /* eslint-enable no-eval */
allTests.push(pub);
allTests.push(priv);
}
allTests = allTests.concat(specialTests);
runAsyncTests(allTests);
}
var tests = [
--- a/toolkit/components/ctypes/tests/unit/test_jsctypes.js
+++ b/toolkit/components/ctypes/tests/unit/test_jsctypes.js
@@ -944,16 +944,17 @@ function run_float_tests(library, t, nam
{toString() { return 7; }},
{valueOf() { return 7; }}];
for (let i = 0; i < vals.length; i++)
do_check_throws(function() { d.value = vals[i]; }, TypeError);
// Check that values roundtrip through toSource() correctly.
function test_roundtrip(tFn, val) {
let f1 = tFn(val);
+ // eslint-disable-next-line no-eval
var f2 = eval(f1.toSource());
do_check_eq(f1.value, f2.value);
}
vals = [Infinity, -Infinity, -0, 0, 1, -1, 1 / 3, -1 / 3, 1 / 4, -1 / 4,
1e-14, -1e-14, 0xfffffffffffff000, -0xfffffffffffff000];
for (let i = 0; i < vals.length; i++)
test_roundtrip(t, vals[i]);
do_check_eq(t(NaN).toSource(), t.toSource() + "(NaN)");
@@ -1538,16 +1539,17 @@ function run_StructType_tests() {
do_check_true(g_a.constructor === g_t.ptr);
do_check_eq(g_a.contents.a, s.b.a);
do_check_throws(function() { s.addressOfField(); }, TypeError);
do_check_throws(function() { s.addressOfField("d"); }, TypeError);
do_check_throws(function() { s.addressOfField("a", 2); }, TypeError);
do_check_eq(s.toSource(), "s_t(4, {\"a\": 7, \"b\": 2}, 10)");
do_check_eq(s.toSource(), s.toString());
+ // eslint-disable-next-line no-eval
var s2 = eval(s.toSource());
do_check_true(s2.constructor === s_t);
do_check_eq(s.b.b, s2.b.b);
// Test that structs can be set from an object using 'value'.
do_check_throws(function() { s.value; }, TypeError);
let s_init = { "a": 2, "b": { "a": 9, "b": 5 }, "c": 13 };
s.value = s_init;
@@ -2036,16 +2038,17 @@ function run_ArrayType_tests() {
do_check_eq(ptrValue(b.addressOfElement(0)), ptrValue(p));
// Test that arrays can be constructed through ImplicitConvert.
let c_t = ctypes.int32_t.array(6);
let c = c_t();
c.value = [1, 2, 3, 4, 5, 6];
do_check_eq(c.toSource(), "ctypes.int32_t.array(6)([1, 2, 3, 4, 5, 6])");
do_check_eq(c.toSource(), c.toString());
+ // eslint-disable-next-line no-eval
var c2 = eval(c.toSource());
do_check_eq(c2.constructor.name, "int32_t[6]");
do_check_eq(c2.length, 6);
do_check_eq(c2[3], c[3]);
c.value = c;
do_check_eq(c[3], 4);
do_check_throws(function() { c.value; }, TypeError);
--- a/toolkit/components/feeds/test/test_xml.js
+++ b/toolkit/components/feeds/test/test_xml.js
@@ -33,16 +33,17 @@ function FeedListener(testcase) {
FeedListener.prototype = {
handleResult(result) {
var feed = result.doc;
try {
do_print("Testing feed " + this.testcase.file.path);
Assert.ok(isIID(feed, Ci.nsIFeed), "Has feed interface");
+ // eslint-disable-next-line no-eval
if (!eval(this.testcase.expect)) {
Assert.ok(false, "expect failed for " + this.testcase.desc);
} else {
Assert.ok(true, "expect passed for " + this.testcase.desc);
}
} catch (e) {
Assert.ok(false, "expect failed for " + this.testcase.desc + " ---- " + e.message);
}
--- a/toolkit/components/passwordmgr/test/mochitest/test_basic_form_autocomplete.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_basic_form_autocomplete.html
@@ -79,21 +79,23 @@ var setupScript = runInParent(function s
Services.logins.addLogin(login8B);
// login8C is added later
Services.logins.addLogin(login10);
} catch (e) {
assert.ok(false, "addLogin threw: " + e);
}
addMessageListener("addLogin", loginVariableName => {
+ // eslint-disable-next-line no-eval
let login = eval(loginVariableName);
assert.ok(!!login, "Login to add is defined: " + loginVariableName);
Services.logins.addLogin(login);
});
addMessageListener("removeLogin", loginVariableName => {
+ // eslint-disable-next-line no-eval
let login = eval(loginVariableName);
assert.ok(!!login, "Login to delete is defined: " + loginVariableName);
Services.logins.removeLogin(login);
});
});
</script>
<p id="display"></p>
--- a/toolkit/components/passwordmgr/test/mochitest/test_insecure_form_field_autocomplete.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_insecure_form_field_autocomplete.html
@@ -78,21 +78,23 @@ var setupScript = runInParent(function s
Services.logins.addLogin(login8B);
// login8C is added later
Services.logins.addLogin(login10);
} catch (e) {
assert.ok(false, "addLogin threw: " + e);
}
addMessageListener("addLogin", loginVariableName => {
+ // eslint-disable-next-line no-eval
let login = eval(loginVariableName);
assert.ok(!!login, "Login to add is defined: " + loginVariableName);
Services.logins.addLogin(login);
});
addMessageListener("removeLogin", loginVariableName => {
+ // eslint-disable-next-line no-eval
let login = eval(loginVariableName);
assert.ok(!!login, "Login to delete is defined: " + loginVariableName);
Services.logins.removeLogin(login);
});
});
</script>
<p id="display"></p>
--- a/toolkit/components/passwordmgr/test/mochitest/test_password_field_autocomplete.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_password_field_autocomplete.html
@@ -49,21 +49,23 @@ var setupScript = runInParent(function s
Services.logins.addLogin(login2);
Services.logins.addLogin(login3);
Services.logins.addLogin(login4);
} catch (e) {
assert.ok(false, "addLogin threw: " + e);
}
addMessageListener("addLogin", loginVariableName => {
+ // eslint-disable-next-line no-eval
let login = eval(loginVariableName);
assert.ok(!!login, "Login to add is defined: " + loginVariableName);
Services.logins.addLogin(login);
});
addMessageListener("removeLogin", loginVariableName => {
+ // eslint-disable-next-line no-eval
let login = eval(loginVariableName);
assert.ok(!!login, "Login to delete is defined: " + loginVariableName);
Services.logins.removeLogin(login);
});
});
</script>
<p id="display"></p>
--- a/toolkit/modules/tests/browser/browser_FinderHighlighter.js
+++ b/toolkit/modules/tests/browser/browser_FinderHighlighter.js
@@ -111,16 +111,17 @@ function promiseTestHighlighterOutput(br
if ("animationCalls" in expectedResult) {
Assert.greaterOrEqual(callCounts.animationCalls.length,
expectedResult.animationCalls[0], `Min. animation calls should match for '${word}'.`);
Assert.lessOrEqual(callCounts.animationCalls.length,
expectedResult.animationCalls[1], `Max. animation calls should match for '${word}'.`);
}
// Allow more specific assertions to be tested in `extraTest`.
+ // eslint-disable-next-line no-eval
extraTest = eval(extraTest);
extraTest(lastMaskNode, lastOutlineNode, rects);
resolve();
}
function stubAnonymousContentNode(domNode, anonNode) {
let originals = [anonNode.setTextContentForElement,
--- a/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
+++ b/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
@@ -717,16 +717,17 @@ xhr.prototype = {
};
this[k](e);
} else {
do_print("Notifying " + item + ", but there are no listeners");
}
}
},
addEventListener(aEvent, aValue, aCapturing) {
+ // eslint-disable-next-line no-eval
eval("this._on" + aEvent + " = aValue");
},
flags: Ci.nsIClassInfo.SINGLETON,
getScriptableHelper: () => null,
getInterfaces(aCount) {
let interfaces = [Ci.nsISupports];
aCount.value = interfaces.length;
return interfaces;
--- a/toolkit/modules/tests/xpcshell/test_Log.js
+++ b/toolkit/modules/tests/xpcshell/test_Log.js
@@ -497,16 +497,17 @@ add_task(function* test_log_err_only() {
/*
* Check that log.error(err) is treated the same as
* log.error(null, err) by the logMessage constructor; the formatMessage()
* tests above ensure that the combination of null text and an error object
* is formatted correctly.
*/
try {
+ // eslint-disable-next-line no-eval
eval("javascript syntax error");
} catch (e) {
log.error(e);
let msg = appender.messages.pop();
do_check_eq(msg.message, null);
do_check_eq(msg.params, e);
}
});
@@ -571,16 +572,17 @@ add_task(function* format_errors() {
let str = pFormat.format(err);
do_check_true(str.includes("ReferenceError"));
do_check_true(str.includes("ERROR_FILE:28"));
do_check_true(str.includes("Ref Error"));
// Test that JS-generated Errors are recognized and formatted.
try {
yield Promise.resolve(); // Scrambles the stack
+ // eslint-disable-next-line no-eval
eval("javascript syntax error");
} catch (e) {
str = pFormat.format(e);
do_check_true(str.includes("SyntaxError: missing ;"));
// Make sure we identified it as an Error and formatted the error location as
// lineNumber:columnNumber.
do_check_true(str.includes(":1:11)"));
// Make sure that we use human-readable stack traces
--- a/toolkit/mozapps/update/content/updates.js
+++ b/toolkit/mozapps/update/content/updates.js
@@ -324,16 +324,17 @@ var gUpdates = {
this.strings = document.getElementById("updateStrings");
var brandStrings = document.getElementById("brandStrings");
this.brandName = brandStrings.getString("brandShortName");
var pages = this.wiz.childNodes;
for (var i = 0; i < pages.length; ++i) {
var page = pages[i];
if (page.localName == "wizardpage")
+ // eslint-disable-next-line no-eval
this._pages[page.pageid] = eval(page.getAttribute("object"));
}
// Cache the standard button labels in case we need to restore them
this._cacheButtonStrings("next");
this._cacheButtonStrings("finish");
this._cacheButtonStrings("extra1");
this._cacheButtonStrings("extra2");
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
@@ -114,16 +114,17 @@ module.exports = {
// No duplicate cases in switch statements
"no-duplicate-case": "error",
// Disallow unnecessary calls to .bind()
"no-extra-bind": "error",
// Disallow eval and setInteral/setTimeout with strings
"no-implied-eval": "error",
+ "no-eval": "error",
// No labels
"no-labels": "error",
// Disallow unnecessary nested blocks
"no-lone-blocks": "error",
// If an if block ends with a return no need for an else block
--- a/tools/lint/eslint/eslint-plugin-mozilla/package.json
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package.json
@@ -1,11 +1,11 @@
{
"name": "eslint-plugin-mozilla",
- "version": "0.2.46",
+ "version": "0.2.47",
"description": "A collection of rules that help enforce JavaScript coding standard in the Mozilla project.",
"keywords": [
"eslint",
"eslintplugin",
"eslint-plugin",
"mozilla",
"firefox"
],