diff --git a/conf/environments.js b/conf/environments.js index ee5ee1b4e5b..90589b1c327 100644 --- a/conf/environments.js +++ b/conf/environments.js @@ -40,7 +40,8 @@ const newGlobals2017 = { const newGlobals2020 = { BigInt: false, BigInt64Array: false, - BigUint64Array: false + BigUint64Array: false, + globalThis: false }; //------------------------------------------------------------------------------ diff --git a/lib/rules/no-alert.js b/lib/rules/no-alert.js index 287cd2c3570..22d0dd57bdd 100644 --- a/lib/rules/no-alert.js +++ b/lib/rules/no-alert.js @@ -8,7 +8,10 @@ // Requirements //------------------------------------------------------------------------------ -const getPropertyName = require("./utils/ast-utils").getStaticPropertyName; +const { + getStaticPropertyName: getPropertyName, + getVariableByName +} = require("./utils/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -61,7 +64,7 @@ function isGlobalThisReferenceOrGlobalWindow(scope, node) { if (scope.type === "global" && node.type === "ThisExpression") { return true; } - if (node.name === "window") { + if (node.name === "window" || (node.name === "globalThis" && getVariableByName(scope, "globalThis"))) { return !isShadowed(scope, node); } @@ -119,7 +122,6 @@ module.exports = { }); } } - } }; diff --git a/lib/rules/no-eval.js b/lib/rules/no-eval.js index a293b04aa37..811ad4e5d73 100644 --- a/lib/rules/no-eval.js +++ b/lib/rules/no-eval.js @@ -17,7 +17,8 @@ const astUtils = require("./utils/ast-utils"); const candidatesOfGlobalObject = Object.freeze([ "global", - "window" + "window", + "globalThis" ]); /** diff --git a/lib/rules/no-obj-calls.js b/lib/rules/no-obj-calls.js index 9ff666b0328..336451656d2 100644 --- a/lib/rules/no-obj-calls.js +++ b/lib/rules/no-obj-calls.js @@ -10,6 +10,7 @@ //------------------------------------------------------------------------------ const { CALL, ReferenceTracker } = require("eslint-utils"); +const getPropertyName = require("./utils/ast-utils").getStaticPropertyName; //------------------------------------------------------------------------------ // Helpers @@ -17,6 +18,18 @@ const { CALL, ReferenceTracker } = require("eslint-utils"); const nonCallableGlobals = ["Atomics", "JSON", "Math", "Reflect"]; +/** + * Returns the name of the node to report + * @param {ASTNode} node A node to report + * @returns {string} name to report + */ +function getReportNodeName(node) { + if (node.callee.type === "MemberExpression") { + return getPropertyName(node.callee); + } + return node.callee.name; +} + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -35,7 +48,8 @@ module.exports = { schema: [], messages: { - unexpectedCall: "'{{name}}' is not a function." + unexpectedCall: "'{{name}}' is not a function.", + unexpectedRefCall: "'{{name}}' is reference to '{{ref}}', which is not a function." } }, @@ -53,8 +67,12 @@ module.exports = { }; } - for (const { node } of tracker.iterateGlobalReferences(traceMap)) { - context.report({ node, messageId: "unexpectedCall", data: { name: node.callee.name } }); + for (const { node, path } of tracker.iterateGlobalReferences(traceMap)) { + const name = getReportNodeName(node); + const ref = path[0]; + const messageId = name === ref ? "unexpectedCall" : "unexpectedRefCall"; + + context.report({ node, messageId, data: { name, ref } }); } } }; diff --git a/package.json b/package.json index 282c5f089ee..e6d91d59f19 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "debug": "^4.0.1", "doctrine": "^3.0.0", "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", + "eslint-utils": "^2.0.0", "eslint-visitor-keys": "^1.1.0", "espree": "^6.2.1", "esquery": "^1.0.1", diff --git a/tests/lib/rules/no-alert.js b/tests/lib/rules/no-alert.js index fd89484a2d1..4851d5b0a7a 100644 --- a/tests/lib/rules/no-alert.js +++ b/tests/lib/rules/no-alert.js @@ -34,7 +34,12 @@ ruleTester.run("no-alert", rule, { "function prompt() {} prompt();", "window[alert]();", "function foo() { this.alert(); }", - "function foo() { var window = bar; window.alert(); }" + "function foo() { var window = bar; window.alert(); }", + "globalThis.alert();", + { code: "globalThis['alert']();", env: { es6: true } }, + { code: "globalThis.alert();", env: { es2017: true } }, + { code: "var globalThis = foo; globalThis.alert();", env: { es2020: true } }, + { code: "function foo() { var globalThis = foo; globalThis.alert(); }", env: { es2020: true } } ], invalid: [ { @@ -104,6 +109,21 @@ ruleTester.run("no-alert", rule, { { code: "function foo() { var window = bar; window.alert(); }\nwindow.alert();", errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 2, column: 1 }] + }, + { + code: "globalThis['alert'](foo)", + env: { es2020: true }, + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "globalThis.alert();", + env: { es2020: true }, + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 1, column: 1 }] + }, + { + code: "function foo() { var globalThis = bar; globalThis.alert(); }\nglobalThis.alert();", + env: { es2020: true }, + errors: [{ messageId: "unexpected", data: { name: "alert" }, type: "CallExpression", line: 2, column: 1 }] } ] }); diff --git a/tests/lib/rules/no-eval.js b/tests/lib/rules/no-eval.js index 4888802a615..ad184bd9370 100644 --- a/tests/lib/rules/no-eval.js +++ b/tests/lib/rules/no-eval.js @@ -35,6 +35,11 @@ ruleTester.run("no-eval", rule, { { code: "global.eval('foo')", env: { browser: true } }, { code: "global.noeval('foo')", env: { node: true } }, { code: "function foo() { var eval = 'foo'; global[eval]('foo') }", env: { node: true } }, + "globalThis.eval('foo')", + { code: "globalThis.eval('foo')", env: { es2017: true } }, + { code: "globalThis.eval('foo')", env: { browser: true } }, + { code: "globalThis.noneval('foo')", env: { es2020: true } }, + { code: "function foo() { var eval = 'foo'; globalThis[eval]('foo') }", env: { es2020: true } }, "this.noeval('foo');", "function foo() { 'use strict'; this.eval('foo'); }", { code: "function foo() { this.eval('foo'); }", parserOptions: { ecmaVersion: 6, sourceType: "module" } }, @@ -57,7 +62,12 @@ ruleTester.run("no-eval", rule, { { code: "global.eval('foo')", options: [{ allowIndirect: true }], env: { node: true } }, { code: "global.global.eval('foo')", options: [{ allowIndirect: true }], env: { node: true } }, { code: "this.eval('foo')", options: [{ allowIndirect: true }] }, - { code: "function foo() { this.eval('foo') }", options: [{ allowIndirect: true }] } + { code: "function foo() { this.eval('foo') }", options: [{ allowIndirect: true }] }, + { code: "(0, globalThis.eval)('foo')", options: [{ allowIndirect: true }], env: { es2020: true } }, + { code: "(0, globalThis['eval'])('foo')", options: [{ allowIndirect: true }], env: { es2020: true } }, + { code: "var EVAL = globalThis.eval; EVAL('foo')", options: [{ allowIndirect: true }] }, + { code: "function foo() { globalThis.eval('foo') }", options: [{ allowIndirect: true }], env: { es2020: true } }, + { code: "globalThis.globalThis.eval('foo');", options: [{ allowIndirect: true }], env: { es2020: true } } ], invalid: [ @@ -84,6 +94,12 @@ ruleTester.run("no-eval", rule, { { code: "global.global.eval('foo')", env: { node: true }, errors: [{ messageId: "unexpected", type: "CallExpression", column: 15, endColumn: 19 }] }, { code: "global.global[`eval`]('foo')", parserOptions: { ecmaVersion: 6 }, env: { node: true }, errors: [{ messageId: "unexpected", type: "CallExpression", column: 15, endColumn: 21 }] }, { code: "this.eval('foo')", errors: [{ messageId: "unexpected", type: "CallExpression", column: 6, endColumn: 10 }] }, - { code: "function foo() { this.eval('foo') }", errors: [{ messageId: "unexpected", type: "CallExpression", column: 23, endColumn: 27 }] } + { code: "function foo() { this.eval('foo') }", errors: [{ messageId: "unexpected", type: "CallExpression", column: 23, endColumn: 27 }] }, + { code: "var EVAL = globalThis.eval; EVAL('foo')", env: { es2020: true }, errors: [{ messageId: "unexpected", type: "MemberExpression", column: 23, endColumn: 27 }] }, + { code: "globalThis.eval('foo')", env: { es2020: true }, errors: [{ messageId: "unexpected", type: "CallExpression", column: 12, endColumn: 16 }] }, + { code: "globalThis.globalThis.eval('foo')", env: { es2020: true }, errors: [{ messageId: "unexpected", type: "CallExpression", column: 23, endColumn: 27 }] }, + { code: "globalThis.globalThis['eval']('foo')", env: { es2020: true }, errors: [{ messageId: "unexpected", type: "CallExpression", column: 23, endColumn: 29 }] }, + { code: "(0, globalThis.eval)('foo')", env: { es2020: true }, errors: [{ messageId: "unexpected", type: "MemberExpression", column: 16, endColumn: 20 }] }, + { code: "(0, globalThis['eval'])('foo')", env: { es2020: true }, errors: [{ messageId: "unexpected", type: "MemberExpression", column: 16, endColumn: 22 }] } ] }); diff --git a/tests/lib/rules/no-misleading-character-class.js b/tests/lib/rules/no-misleading-character-class.js index b4b3ac530a3..a7bc04ef415 100644 --- a/tests/lib/rules/no-misleading-character-class.js +++ b/tests/lib/rules/no-misleading-character-class.js @@ -67,7 +67,9 @@ ruleTester.run("no-misleading-character-class", rule, { // don't report and don't crash on invalid regex "var r = new RegExp('[Á] [ ');", - "var r = RegExp('{ [Á]', 'u');" + "var r = RegExp('{ [Á]', 'u');", + { code: "var r = new globalThis.RegExp('[Á] [ ');", env: { es2020: true } }, + { code: "var r = globalThis.RegExp('{ [Á]', 'u');", env: { es2020: true } } ], invalid: [ @@ -271,6 +273,26 @@ ruleTester.run("no-misleading-character-class", rule, { { code: String.raw`var r = new RegExp("[\\u{1F468}\\u{200D}\\u{1F469}\\u{200D}\\u{1F466}]", "u")`, errors: [{ messageId: "zwj" }] + }, + { + code: String.raw`var r = new globalThis.RegExp("[❇️]", "")`, + env: { es2020: true }, + errors: [{ messageId: "combiningClass" }] + }, + { + code: String.raw`var r = new globalThis.RegExp("[👶🏻]", "u")`, + env: { es2020: true }, + errors: [{ messageId: "emojiModifier" }] + }, + { + code: String.raw`var r = new globalThis.RegExp("[🇯🇵]", "")`, + env: { es2020: true }, + errors: [{ messageId: "surrogatePairWithoutUFlag" }] + }, + { + code: String.raw`var r = new globalThis.RegExp("[\\u{1F468}\\u{200D}\\u{1F469}\\u{200D}\\u{1F466}]", "u")`, + env: { es2020: true }, + errors: [{ messageId: "zwj" }] } ] }); diff --git a/tests/lib/rules/no-obj-calls.js b/tests/lib/rules/no-obj-calls.js index df0c39afb5a..d0aea3cb2db 100644 --- a/tests/lib/rules/no-obj-calls.js +++ b/tests/lib/rules/no-obj-calls.js @@ -28,6 +28,19 @@ ruleTester.run("no-obj-calls", rule, { "Reflect.get(foo, 'x')", "Atomics.load(foo, 0)", + { code: "globalThis.Math();", env: { es6: true } }, + { code: "var x = globalThis.Math();", env: { es6: true } }, + { code: "f(globalThis.Math());", env: { es6: true } }, + { code: "globalThis.Math().foo;", env: { es6: true } }, + { code: "var x = globalThis.JSON();", env: { es6: true } }, + { code: "x = globalThis.JSON(str);", env: { es6: true } }, + { code: "globalThis.Math( globalThis.JSON() );", env: { es6: true } }, + { code: "var x = globalThis.Reflect();", env: { es6: true } }, + { code: "var x = globalThis.Reflect();", env: { es2017: true } }, + { code: "/*globals Reflect: true*/ globalThis.Reflect();", env: { es2017: true } }, + { code: "var x = globalThis.Atomics();", env: { es2017: true } }, + { code: "var x = globalThis.Atomics();", globals: { Atomics: false }, env: { es2017: true } }, + // non-existing variables "/*globals Math: off*/ Math();", { @@ -129,6 +142,68 @@ ruleTester.run("no-obj-calls", rule, { code: "var x = Atomics();", globals: { Atomics: false }, errors: [{ messageId: "unexpectedCall", data: { name: "Atomics" }, type: "CallExpression" }] + }, + { + code: "var x = globalThis.Math();", + env: { es2020: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Math" }, type: "CallExpression" }] + }, + { + code: "f(globalThis.Math());", + env: { es2020: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Math" }, type: "CallExpression", column: 3, endColumn: 20 }] + }, + { + code: "globalThis.Math().foo;", + env: { es2020: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Math" }, type: "CallExpression", column: 1, endColumn: 18 }] + }, + { + code: "var x = globalThis.JSON();", + env: { es2020: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "JSON" }, type: "CallExpression" }] + }, + { + code: "x = globalThis.JSON(str);", + env: { es2020: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "JSON" }, type: "CallExpression" }] + }, + { + code: "globalThis.Math( globalThis.JSON() );", + env: { es2020: true }, + errors: [ + { messageId: "unexpectedCall", data: { name: "Math" }, type: "CallExpression", column: 1, endColumn: 37 }, + { messageId: "unexpectedCall", data: { name: "JSON" }, type: "CallExpression", column: 18, endColumn: 35 } + ] + }, + { + code: "var x = globalThis.Reflect();", + env: { es2020: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Reflect" }, type: "CallExpression" }] + }, + { + code: "/*globals Reflect: true*/ Reflect();", + env: { es2020: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Reflect" }, type: "CallExpression" }] + }, + { + code: "var x = globalThis.Atomics();", + env: { es2020: true }, + errors: [{ messageId: "unexpectedCall", data: { name: "Atomics" }, type: "CallExpression" }] + }, + { + code: "var foo = bar ? baz: JSON; foo();", + errors: [{ messageId: "unexpectedRefCall", data: { name: "foo", ref: "JSON" }, type: "CallExpression" }] + }, + { + code: "var foo = bar ? baz: globalThis.JSON; foo();", + env: { es2020: true }, + errors: [{ messageId: "unexpectedRefCall", data: { name: "foo", ref: "JSON" }, type: "CallExpression" }] + }, + { + code: "var foo = window.Atomics; foo();", + env: { es2020: true, browser: true }, + errors: [{ messageId: "unexpectedRefCall", data: { name: "foo", ref: "Atomics" }, type: "CallExpression" }] } ] }); diff --git a/tests/lib/rules/no-redeclare.js b/tests/lib/rules/no-redeclare.js index 47c8146b14a..f5ced80f328 100644 --- a/tests/lib/rules/no-redeclare.js +++ b/tests/lib/rules/no-redeclare.js @@ -41,6 +41,8 @@ ruleTester.run("no-redeclare", rule, { options: [{ builtinGlobals: true }], env: { browser: false } }, + { code: "var glovalThis = foo", options: [{ builtinGlobals: true }], env: { es6: true } }, + { code: "var glovalThis = foo", options: [{ builtinGlobals: true }], env: { es2017: true } }, // Comments and built-ins. { @@ -124,6 +126,22 @@ ruleTester.run("no-redeclare", rule, { { message: "'a' is already defined.", type: "Identifier" } ] }, + { + code: "var globalThis = 0;", + options: [{ builtinGlobals: true }], + env: { es2020: true }, + errors: [{ message: "'globalThis' is already defined as a built-in global variable.", type: "Identifier" }] + }, + { + code: "var a; var {a = 0, b: globalThis = 0} = {};", + options: [{ builtinGlobals: true }], + parserOptions: { ecmaVersion: 6 }, + env: { es2020: true }, + errors: [ + { message: "'a' is already defined.", type: "Identifier" }, + { message: "'globalThis' is already defined as a built-in global variable.", type: "Identifier" } + ] + }, { code: "/*global b:false*/ var b = 1;", options: [{ builtinGlobals: true }], diff --git a/tests/lib/rules/prefer-exponentiation-operator.js b/tests/lib/rules/prefer-exponentiation-operator.js index 0c7890ea921..42bf8ec047d 100644 --- a/tests/lib/rules/prefer-exponentiation-operator.js +++ b/tests/lib/rules/prefer-exponentiation-operator.js @@ -58,6 +58,8 @@ ruleTester.run("prefer-exponentiation-operator", rule, { "foo.Math.pow(a, b)", "new Math.pow(a, b)", "Math[pow](a, b)", + { code: "globalThis.Object.pow(a, b)", env: { es2020: true } }, + { code: "globalThis.Math.max(a, b)", env: { es2020: true } }, // not the global Math "/* globals Math:off*/ Math.pow(a, b)", @@ -65,7 +67,18 @@ ruleTester.run("prefer-exponentiation-operator", rule, { "if (foo) { const Math = 1; Math.pow(a, b); }", "var x = function Math() { Math.pow(a, b); }", "function foo(Math) { Math.pow(a, b); }", - "function foo() { Math.pow(a, b); var Math; }" + "function foo() { Math.pow(a, b); var Math; }", + + "globalThis.Math.pow(a, b)", + { code: "globalThis.Math.pow(a, b)", env: { es6: true } }, + { code: "globalThis.Math.pow(a, b)", env: { es2017: true } }, + { + code: ` + var globalThis = bar; + globalThis.Math.pow(a, b) + `, + env: { es2020: true } + } ], invalid: [ @@ -75,6 +88,36 @@ ruleTester.run("prefer-exponentiation-operator", rule, { invalid("Math['pow'](a, b)", "a**b"), invalid("(Math)['pow'](a, b)", "a**b"), invalid("var x=Math\n. pow( a, \n b )", "var x=a**b"), + { + code: "globalThis.Math.pow(a, b)", + output: "a**b", + env: { es2020: true }, + errors: [ + { + messageId: "useExponentiation", + type: "CallExpression", + line: 1, + column: 1, + endLine: 1, + endColumn: 26 + } + ] + }, + { + code: "globalThis.Math['pow'](a, b)", + output: "a**b", + env: { es2020: true }, + errors: [ + { + messageId: "useExponentiation", + type: "CallExpression", + line: 1, + column: 1, + endLine: 1, + endColumn: 29 + } + ] + }, // able to catch some workarounds invalid("Math[`pow`](a, b)", "a**b"), diff --git a/tests/lib/rules/prefer-named-capture-group.js b/tests/lib/rules/prefer-named-capture-group.js index 4444ef479c0..0faf1d6be65 100644 --- a/tests/lib/rules/prefer-named-capture-group.js +++ b/tests/lib/rules/prefer-named-capture-group.js @@ -33,7 +33,44 @@ ruleTester.run("prefer-named-capture-group", rule, { "RegExp('')", "RegExp('(?[0-9]{4})')", "RegExp('(')", // invalid regexp should be ignored - "RegExp('\\\\u{1F680}', 'u')" + "RegExp('\\\\u{1F680}', 'u')", + "new globalThis.RegExp('([0-9]{4})')", + { + code: "new globalThis.RegExp('([0-9]{4})')", + env: { es6: true } + }, + { + code: "new globalThis.RegExp('([0-9]{4})')", + env: { es2017: true } + }, + { + code: "new globalThis.RegExp()", + env: { es2020: true } + }, + { + code: "new globalThis.RegExp(foo)", + env: { es2020: true } + }, + { + code: "globalThis.RegExp(foo)", + env: { es2020: true } + }, + { + code: ` + var globalThis = bar; + globalThis.RegExp(foo); + `, + env: { es2020: true } + }, + { + code: ` + function foo () { + var globalThis = bar; + new globalThis.RegExp(baz); + } + `, + env: { es2020: true } + } ], invalid: [ @@ -182,6 +219,45 @@ ruleTester.run("prefer-named-capture-group", rule, { type: "CallExpression", data: { group: "(b)" } }] + }, + { + code: "new globalThis.RegExp('([0-9]{4})')", + env: { es2020: true }, + errors: [{ + messageId: "required", + type: "NewExpression", + data: { group: "([0-9]{4})" }, + line: 1, + column: 1, + endColumn: 36 + }] + }, + { + code: "globalThis.RegExp('([0-9]{4})')", + env: { es2020: true }, + errors: [{ + messageId: "required", + type: "CallExpression", + data: { group: "([0-9]{4})" }, + line: 1, + column: 1, + endColumn: 32 + }] + }, + { + code: ` + function foo() { var globalThis = bar; } + new globalThis.RegExp('([0-9]{4})'); + `, + env: { es2020: true }, + errors: [{ + messageId: "required", + type: "NewExpression", + data: { group: "([0-9]{4})" }, + line: 3, + column: 17, + endColumn: 52 + }] } ] }); diff --git a/tests/lib/rules/prefer-object-spread.js b/tests/lib/rules/prefer-object-spread.js index 9ec3cf630fd..c2b32e15b19 100644 --- a/tests/lib/rules/prefer-object-spread.js +++ b/tests/lib/rules/prefer-object-spread.js @@ -60,6 +60,22 @@ ruleTester.run("prefer-object-spread", rule, { import { Object, Array } from 'globals'; Object.assign({ foo: 'bar' }); `, + "globalThis.Object.assign({}, foo)", + { + code: "globalThis.Object.assign({}, { foo: 'bar' })", + env: { es6: true } + }, + { + code: "globalThis.Object.assign({}, baz, { foo: 'bar' })", + env: { es2017: true } + }, + { + code: ` + var globalThis = foo; + globalThis.Object.assign({}, foo) + `, + env: { es2020: true } + }, // ignore Object.assign() with > 1 arguments if any of the arguments is an object expression with a getter/setter "Object.assign({ get a() {} }, {})", @@ -847,6 +863,70 @@ ruleTester.run("prefer-object-spread", rule, { } ] }, + { + code: "globalThis.Object.assign({ });", + output: "({});", + env: { es2020: true }, + errors: [ + { + messageId: "useLiteralMessage", + type: "CallExpression", + line: 1, + column: 1 + } + ] + }, + { + code: "globalThis.Object.assign({\n});", + output: "({});", + env: { es2020: true }, + errors: [ + { + messageId: "useLiteralMessage", + type: "CallExpression", + line: 1, + column: 1 + } + ] + }, + { + code: ` + function foo () { var globalThis = bar; } + globalThis.Object.assign({ }); + `, + output: ` + function foo () { var globalThis = bar; } + ({}); + `, + env: { es2020: true }, + errors: [ + { + messageId: "useLiteralMessage", + type: "CallExpression", + line: 3, + column: 17 + } + ] + }, + { + code: ` + const Foo = require('foo'); + globalThis.Object.assign({ foo: Foo }); + `, + output: ` + const Foo = require('foo'); + ({foo: Foo}); + `, + env: { es2020: true }, + errors: [ + { + messageId: "useLiteralMessage", + type: "CallExpression", + line: 3, + column: 17 + } + ] + }, // report Object.assign() with getters/setters if the function call has only 1 argument { diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index cfcddbec7d7..65979de83f9 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -90,6 +90,15 @@ ruleTester.run("prefer-regex-literals", rule, { { code: "RegExp('a');", globals: { RegExp: "off" } + }, + "new globalThis.RegExp('a');", + { + code: "new globalThis.RegExp('a');", + env: { es6: true } + }, + { + code: "new globalThis.RegExp('a');", + env: { es2017: true } } ], @@ -177,6 +186,16 @@ ruleTester.run("prefer-regex-literals", rule, { { code: "RegExp('a', String.raw`g`);", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new globalThis.RegExp('a');", + env: { es2020: true }, + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "globalThis.RegExp('a');", + env: { es2020: true }, + errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] } ] }); diff --git a/tests/lib/rules/require-unicode-regexp.js b/tests/lib/rules/require-unicode-regexp.js index 18f5fb25c90..6033d44ca32 100644 --- a/tests/lib/rules/require-unicode-regexp.js +++ b/tests/lib/rules/require-unicode-regexp.js @@ -33,7 +33,14 @@ ruleTester.run("require-unicode-regexp", rule, { "const flags = 'gimu'; new RegExp('foo', flags[3])", "new RegExp('', flags)", "function f(flags) { return new RegExp('', flags) }", - "function f(RegExp) { return new RegExp('foo') }" + "function f(RegExp) { return new RegExp('foo') }", + { code: "new globalThis.RegExp('foo')", env: { es6: true } }, + { code: "new globalThis.RegExp('foo')", env: { es2017: true } }, + { code: "new globalThis.RegExp('foo', 'u')", env: { es2020: true } }, + { code: "globalThis.RegExp('foo', 'u')", env: { es2020: true } }, + { code: "const flags = 'u'; new globalThis.RegExp('', flags)", env: { es2020: true } }, + { code: "const flags = 'g'; new globalThis.RegExp('', flags + 'u')", env: { es2020: true } }, + { code: "const flags = 'gimu'; new globalThis.RegExp('foo', flags[3])", env: { es2020: true } } ], invalid: [ { @@ -85,6 +92,11 @@ ruleTester.run("require-unicode-regexp", rule, { code: "new global.RegExp('foo')", env: { node: true }, errors: [{ messageId: "requireUFlag" }] + }, + { + code: "new globalThis.RegExp('foo')", + env: { es2020: true }, + errors: [{ messageId: "requireUFlag" }] } ] });