From b262df13858421015caa243259161977c2c26604 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 13:46:02 +0800 Subject: [PATCH 01/70] Add `prefer-global-this` rule --- docs/rules/prefer-global-this.md | 33 +++ readme.md | 1 + rules/prefer-global-this.js | 113 +++++++++ test/prefer-global-this.mjs | 45 ++++ test/snapshots/prefer-global-this.mjs.md | 280 +++++++++++++++++++++ test/snapshots/prefer-global-this.mjs.snap | Bin 0 -> 676 bytes 6 files changed, 472 insertions(+) create mode 100644 docs/rules/prefer-global-this.md create mode 100644 rules/prefer-global-this.js create mode 100644 test/prefer-global-this.mjs create mode 100644 test/snapshots/prefer-global-this.mjs.md create mode 100644 test/snapshots/prefer-global-this.mjs.snap diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md new file mode 100644 index 0000000000..d556e85ecb --- /dev/null +++ b/docs/rules/prefer-global-this.md @@ -0,0 +1,33 @@ +# Prefer `globalThis` instead of `window` and `global` + +💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs-eslintconfigjs). + +🔧💡 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) and manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). + + + + +## Fail + +```js +window +window.foo +window[foo] +window.foo() +global +global.foo +global[foo] +global.foo() +const { foo } = window +const { foo } = global +``` + +## Pass + +```js +globalThis +globalThis.foo +globalThis[foo] +globalThis.foo() +const { foo } = globalThis +``` diff --git a/readme.md b/readme.md index 33619961eb..fbcc4aef10 100644 --- a/readme.md +++ b/readme.md @@ -189,6 +189,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c | [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. | ✅ | | 💡 | | [prefer-event-target](docs/rules/prefer-event-target.md) | Prefer `EventTarget` over `EventEmitter`. | ✅ | | | | [prefer-export-from](docs/rules/prefer-export-from.md) | Prefer `export…from` when re-exporting. | ✅ | 🔧 | 💡 | +| [prefer-global-this](docs/rules/prefer-global-this.md) | Prefer `globalThis` instead of `window` and `global`. | ✅ | 🔧 | 💡 | | [prefer-includes](docs/rules/prefer-includes.md) | Prefer `.includes()` over `.indexOf()`, `.lastIndexOf()`, and `Array#some()` when checking for existence or non-existence. | ✅ | 🔧 | 💡 | | [prefer-json-parse-buffer](docs/rules/prefer-json-parse-buffer.md) | Prefer reading a JSON file as a buffer. | | 🔧 | | | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | ✅ | 🔧 | | diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js new file mode 100644 index 0000000000..93e3884d52 --- /dev/null +++ b/rules/prefer-global-this.js @@ -0,0 +1,113 @@ +'use strict'; + +const MESSAGE_ID_ERROR = 'prefer-global-this/error'; +const MESSAGE_ID_SUGGESTION = 'prefer-global-this/suggestion'; +const messages = { + [MESSAGE_ID_ERROR]: 'Prefer `{{replacement}}` over `{{value}}`.', + [MESSAGE_ID_SUGGESTION]: 'Replace `{{value}}` with `{{replacement}}`.', +}; + +/** + * Find the variable in the scope + * @param {import('eslint').Scope.Scope} scope + * @param {string} variableName + * @returns + */ +function findVariableInScope(scope, variableName) { + if (!scope || scope.type === 'global') { + return undefined; + } + + const variable = scope.variables.find(v => v.name === variableName); + + if (variable) { + return variable; + } + + return findVariableInScope(scope.upper, variableName); +} + +/** @param {import('eslint').Rule.RuleContext} context */ +const create = context => ({ + Identifier(node) { + if (node.name !== 'window' && node.name !== 'global') { + return; + } + + const ancestors = context.sourceCode.getAncestors(node); + + const parent = ancestors.length > 0 ? ancestors.at(-1) : undefined; + + // Skip `window` and `global` in function declarations and variable declarations. + if (parent) { + if (['FunctionDeclaration', 'FunctionExpression'].includes(parent.type)) { + // Skip `function window() {}` and `function global() {}` + if (parent.id === node) { + return; + } + + // Skip `function foo(window) {}` and `function foo(global) {}` + if (parent.params.includes(node)) { + return; + } + + return; + } + + // Skip `var window = 1;` and `var global = 1;` + if (parent.type === 'VariableDeclarator' && parent.id === node) { + return; + } + } + + const variable = findVariableInScope( + context.sourceCode.getScope(node), + node.name, + ); + + // Skip that has been declared in the scope + if (variable) { + return; + } + + return { + node, + messageId: MESSAGE_ID_ERROR, + data: { + value: node.name, + replacement: 'globalThis', + }, + + /** @param {import('eslint').Rule.RuleFixer} fixer */ + fix: fixer => fixer.replaceText(node, 'globalThis'), + + /** @param {import('eslint').Rule.RuleFixer} fixer */ + suggest: [ + { + messageId: MESSAGE_ID_SUGGESTION, + data: { + value: node.name, + replacement: 'globalThis', + }, + /** @param {import('eslint').Rule.RuleFixer} fixer */ + fix: fixer => fixer.replaceText(node, 'globalThis'), + }, + ], + }; + }, +}); + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + create, + meta: { + type: 'suggestion', + docs: { + description: 'Prefer `globalThis` instead of `window` and `global`.', + recommended: true, + }, + fixable: 'code', + hasSuggestions: true, + messages, + }, +}; diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs new file mode 100644 index 0000000000..438e24de2d --- /dev/null +++ b/test/prefer-global-this.mjs @@ -0,0 +1,45 @@ +import {getTester} from './utils/test.mjs'; +import outdent from 'outdent'; + +const {test} = getTester(import.meta); + +test.snapshot({ + valid: [ + 'globalThis', + 'globalThis.foo', + 'globalThis[foo]', + 'globalThis.foo()', + 'const { foo } = globalThis', + 'function foo (window) {}', + 'function foo (global) {}', + 'var foo = function foo (window) {}', + 'var foo = function foo (global) {}', + 'var window = {}', + 'let global = {}', + 'const global = {}', + outdent` + function foo (window) { + window.foo(); + } + `, + outdent` + var window = {}; + function foo () { + window.foo(); + } + `, + ], + invalid: [ + 'window', + 'window.foo', + 'window[foo]', + 'window.foo()', + 'global', + 'global.foo', + 'global[foo]', + 'global.foo()', + 'const { foo } = window', + 'const { foo } = global', + 'function foo() { window.foo() }', + ], +}); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md new file mode 100644 index 0000000000..7787d4a304 --- /dev/null +++ b/test/snapshots/prefer-global-this.mjs.md @@ -0,0 +1,280 @@ +# Snapshot report for `test/prefer-global-this.mjs` + +The actual snapshot is saved in `prefer-global-this.mjs.snap`. + +Generated by [AVA](https://avajs.dev). + +## invalid(1): window + +> Input + + `␊ + 1 | window␊ + ` + +> Output + + `␊ + 1 | globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis␊ + ` + +## invalid(2): window.foo + +> Input + + `␊ + 1 | window.foo␊ + ` + +> Output + + `␊ + 1 | globalThis.foo␊ + ` + +> Error 1/1 + + `␊ + > 1 | window.foo␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.foo␊ + ` + +## invalid(3): window[foo] + +> Input + + `␊ + 1 | window[foo]␊ + ` + +> Output + + `␊ + 1 | globalThis[foo]␊ + ` + +> Error 1/1 + + `␊ + > 1 | window[foo]␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis[foo]␊ + ` + +## invalid(4): window.foo() + +> Input + + `␊ + 1 | window.foo()␊ + ` + +> Output + + `␊ + 1 | globalThis.foo()␊ + ` + +> Error 1/1 + + `␊ + > 1 | window.foo()␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.foo()␊ + ` + +## invalid(5): global + +> Input + + `␊ + 1 | global␊ + ` + +> Output + + `␊ + 1 | globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | global␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | globalThis␊ + ` + +## invalid(6): global.foo + +> Input + + `␊ + 1 | global.foo␊ + ` + +> Output + + `␊ + 1 | globalThis.foo␊ + ` + +> Error 1/1 + + `␊ + > 1 | global.foo␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | globalThis.foo␊ + ` + +## invalid(7): global[foo] + +> Input + + `␊ + 1 | global[foo]␊ + ` + +> Output + + `␊ + 1 | globalThis[foo]␊ + ` + +> Error 1/1 + + `␊ + > 1 | global[foo]␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | globalThis[foo]␊ + ` + +## invalid(8): global.foo() + +> Input + + `␊ + 1 | global.foo()␊ + ` + +> Output + + `␊ + 1 | globalThis.foo()␊ + ` + +> Error 1/1 + + `␊ + > 1 | global.foo()␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | globalThis.foo()␊ + ` + +## invalid(9): const { foo } = window + +> Input + + `␊ + 1 | const { foo } = window␊ + ` + +> Output + + `␊ + 1 | const { foo } = globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | const { foo } = window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | const { foo } = globalThis␊ + ` + +## invalid(10): const { foo } = global + +> Input + + `␊ + 1 | const { foo } = global␊ + ` + +> Output + + `␊ + 1 | const { foo } = globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | const { foo } = global␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | const { foo } = globalThis␊ + ` + +## invalid(11): function foo() { window.foo() } + +> Input + + `␊ + 1 | function foo() { window.foo() }␊ + ` + +> Output + + `␊ + 1 | function foo() { globalThis.foo() }␊ + ` + +> Error 1/1 + + `␊ + > 1 | function foo() { window.foo() }␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | function foo() { globalThis.foo() }␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap new file mode 100644 index 0000000000000000000000000000000000000000..a91a9f73475194e238e77584bff0b0bb492529f5 GIT binary patch literal 676 zcmV;V0$cq-RzVu)LAINh-BHapWoJJ8?t^i6cTh0*bv}?_}4FgNjAHM{B>C&HQHkt@GLKdaU;$ z{B%S($~#emv^;9qzooa<+1=GF#P^%K7T51<-;6 zvD+e^(W{`;><6^}g4jRsSl97h4QVJe?z1sZML$&0nJ*RVv6=+{-~ir73!VqW zB>{BOh#g>)*^_v8r)gPtPIy@_$AbY0Ib}YyHd}3YK}Md_BQhsUDIcOUHM4#=eG&vL zn1vA(CJBYRl0wsEOebNkY^pHPxPdg6v_mO6Oynmb@)Z+_ROO(e6hI?0O~`CZGH+eR z-sxzrp)y}YXd;P;%}pe_tQ}1iVmQALoNpLTEGq{cwFDZTy;{QO9-5qntplo~TCZud z)38m1ZXs38*gR5+5&cGpzU%YTuuH-S6+wd}J!Z#l3sGK=iFf~Nj}cjNvWTA)%R=Nl z5s$eqDJeTN-mFiAjvG{F^Z%Rk5TiLgHBG5d59(_zsIPWVmt5&!@tzBD-i literal 0 HcmV?d00001 From 23b9b1832f6d2f37f5bdf5e0fd8d8b459e746d1f Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 13:57:16 +0800 Subject: [PATCH 02/70] fix: add more test --- rules/prefer-global-this.js | 46 ++++--- test/prefer-global-this.mjs | 7 + test/snapshots/prefer-global-this.mjs.md | 147 +++++++++++++++++++++ test/snapshots/prefer-global-this.mjs.snap | Bin 676 -> 876 bytes 4 files changed, 182 insertions(+), 18 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 93e3884d52..a2b7f4b3ed 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -1,10 +1,10 @@ -'use strict'; +"use strict"; -const MESSAGE_ID_ERROR = 'prefer-global-this/error'; -const MESSAGE_ID_SUGGESTION = 'prefer-global-this/suggestion'; +const MESSAGE_ID_ERROR = "prefer-global-this/error"; +const MESSAGE_ID_SUGGESTION = "prefer-global-this/suggestion"; const messages = { - [MESSAGE_ID_ERROR]: 'Prefer `{{replacement}}` over `{{value}}`.', - [MESSAGE_ID_SUGGESTION]: 'Replace `{{value}}` with `{{replacement}}`.', + [MESSAGE_ID_ERROR]: "Prefer `{{replacement}}` over `{{value}}`.", + [MESSAGE_ID_SUGGESTION]: "Replace `{{value}}` with `{{replacement}}`.", }; /** @@ -14,11 +14,11 @@ const messages = { * @returns */ function findVariableInScope(scope, variableName) { - if (!scope || scope.type === 'global') { + if (!scope || scope.type === "global") { return undefined; } - const variable = scope.variables.find(v => v.name === variableName); + const variable = scope.variables.find((v) => v.name === variableName); if (variable) { return variable; @@ -28,9 +28,9 @@ function findVariableInScope(scope, variableName) { } /** @param {import('eslint').Rule.RuleContext} context */ -const create = context => ({ +const create = (context) => ({ Identifier(node) { - if (node.name !== 'window' && node.name !== 'global') { + if (node.name !== "window" && node.name !== "global") { return; } @@ -40,7 +40,7 @@ const create = context => ({ // Skip `window` and `global` in function declarations and variable declarations. if (parent) { - if (['FunctionDeclaration', 'FunctionExpression'].includes(parent.type)) { + if (["FunctionDeclaration", "FunctionExpression"].includes(parent.type)) { // Skip `function window() {}` and `function global() {}` if (parent.id === node) { return; @@ -55,7 +55,17 @@ const create = context => ({ } // Skip `var window = 1;` and `var global = 1;` - if (parent.type === 'VariableDeclarator' && parent.id === node) { + if (parent.type === "VariableDeclarator" && parent.id === node) { + return; + } + + // Skip `foo.window` and `foo.global`, but not allow `window.window` and `global.global + if ( + parent.type === "MemberExpression" && + parent.property === node && + parent.object.type === "Identifier" && + parent.object.name !== node.name + ) { return; } } @@ -75,11 +85,11 @@ const create = context => ({ messageId: MESSAGE_ID_ERROR, data: { value: node.name, - replacement: 'globalThis', + replacement: "globalThis", }, /** @param {import('eslint').Rule.RuleFixer} fixer */ - fix: fixer => fixer.replaceText(node, 'globalThis'), + fix: (fixer) => fixer.replaceText(node, "globalThis"), /** @param {import('eslint').Rule.RuleFixer} fixer */ suggest: [ @@ -87,10 +97,10 @@ const create = context => ({ messageId: MESSAGE_ID_SUGGESTION, data: { value: node.name, - replacement: 'globalThis', + replacement: "globalThis", }, /** @param {import('eslint').Rule.RuleFixer} fixer */ - fix: fixer => fixer.replaceText(node, 'globalThis'), + fix: (fixer) => fixer.replaceText(node, "globalThis"), }, ], }; @@ -101,12 +111,12 @@ const create = context => ({ module.exports = { create, meta: { - type: 'suggestion', + type: "suggestion", docs: { - description: 'Prefer `globalThis` instead of `window` and `global`.', + description: "Prefer `globalThis` instead of `window` and `global`.", recommended: true, }, - fixable: 'code', + fixable: "code", hasSuggestions: true, messages, }, diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 438e24de2d..fbbdc043a2 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -28,6 +28,8 @@ test.snapshot({ window.foo(); } `, + 'foo.window', + 'foo.global', ], invalid: [ 'window', @@ -41,5 +43,10 @@ test.snapshot({ 'const { foo } = window', 'const { foo } = global', 'function foo() { window.foo() }', + 'foo(window)', + "window.window", + "global.global", + "window.global", + "global.window", ], }); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 7787d4a304..06d194e58c 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -278,3 +278,150 @@ Generated by [AVA](https://avajs.dev). Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ 1 | function foo() { globalThis.foo() }␊ ` + +## invalid(12): foo(window) + +> Input + + `␊ + 1 | foo(window)␊ + ` + +> Output + + `␊ + 1 | foo(globalThis)␊ + ` + +> Error 1/1 + + `␊ + > 1 | foo(window)␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | foo(globalThis)␊ + ` + +## invalid(13): window.window + +> Input + + `␊ + 1 | window.window␊ + ` + +> Output + + `␊ + 1 | globalThis.globalThis␊ + ` + +> Error 1/2 + + `␊ + > 1 | window.window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.window␊ + ` + +> Error 2/2 + + `␊ + > 1 | window.window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | window.globalThis␊ + ` + +## invalid(14): global.global + +> Input + + `␊ + 1 | global.global␊ + ` + +> Output + + `␊ + 1 | globalThis.globalThis␊ + ` + +> Error 1/2 + + `␊ + > 1 | global.global␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | globalThis.global␊ + ` + +> Error 2/2 + + `␊ + > 1 | global.global␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | global.globalThis␊ + ` + +## invalid(15): window.global + +> Input + + `␊ + 1 | window.global␊ + ` + +> Output + + `␊ + 1 | globalThis.global␊ + ` + +> Error 1/1 + + `␊ + > 1 | window.global␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.global␊ + ` + +## invalid(16): global.window + +> Input + + `␊ + 1 | global.window␊ + ` + +> Output + + `␊ + 1 | globalThis.window␊ + ` + +> Error 1/1 + + `␊ + > 1 | global.window␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | globalThis.window␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index a91a9f73475194e238e77584bff0b0bb492529f5..181eaaa98d184f636bc9e5dc49510b4a06ec2f54 100644 GIT binary patch literal 876 zcmV-y1C#tgRzV`IB)_12M_`^ zZId=4imN1TCv7{yAHcuB{wIzIAvhs~5I1fpjpO*$c7C7{t;sR+*Ux#MXMdmb!RT7J z_r`sHpnIlg>5genG|TMQ)Os6DO}me$rfX{>cZfar?LohO?bk5T5vNg3+CZqTD>>M|nCP40P8sv5nLXwT+(WBTMV)G$xvw-Vm&* zA^ULif#YDupN3GFgcO>TLc_qACn3&kq!7`#1~limMKL-^nMp)!t^?6|ZfUF#!ubi{e1>oWSuyCaDd6zzR6;&mVCU58 zJfJGb^)k12YIPBz8$eYN77tZIM85!{FZ}+g)eFK1B!PoOJ*HJ}6H!`^2}b{Kk0DV~ zvIySf%Ywu_6py)0DP-}ONRfxfFwu%ZC6&kAp=2_73?s?KW7v4bpp(*L?t-0@-eXuz zJ{|)i7K2f|$Lv%?NZa)`>S5dU&@M7CM*HZV^kTCP5`Trn6stwxHi5n>(Z`$8i}EsH zxKt(#CCdnC&OeLUK_q61=e$BMteXPRvhE@sXnD7hD`?P;WCndCxA8xKUZV-gNfE;6U`q~bh5b`SOqmu32Pu}Vd7#~&~2YS zc`;_J`u|G&(Lp$Y8H>9mMv}f;@!TDCXIO$ zen;}Q0y2IU-pl3Qy9Q*J`FcU6o{s(%3?DG;VK9RL6u CWS#{8 literal 676 zcmV;V0$cq-RzVu)LAINh-BHapWoJJ8?t^i6cTh0*bv}?_}4FgNjAHM{B>C&HQHkt@GLKdaU;$ z{B%S($~#emv^;9qzooa<+1=GF#P^%K7T51<-;6 zvD+e^(W{`;><6^}g4jRsSl97h4QVJe?z1sZML$&0nJ*RVv6=+{-~ir73!VqW zB>{BOh#g>)*^_v8r)gPtPIy@_$AbY0Ib}YyHd}3YK}Md_BQhsUDIcOUHM4#=eG&vL zn1vA(CJBYRl0wsEOebNkY^pHPxPdg6v_mO6Oynmb@)Z+_ROO(e6hI?0O~`CZGH+eR z-sxzrp)y}YXd;P;%}pe_tQ}1iVmQALoNpLTEGq{cwFDZTy;{QO9-5qntplo~TCZud z)38m1ZXs38*gR5+5&cGpzU%YTuuH-S6+wd}J!Z#l3sGK=iFf~Nj}cjNvWTA)%R=Nl z5s$eqDJeTN-mFiAjvG{F^Z%Rk5TiLgHBG5d59(_zsIPWVmt5&!@tzBD-i From 63333a2aa545359cbc1bf8392aa3443ea9299e7a Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 14:00:08 +0800 Subject: [PATCH 03/70] fix: lint --- rules/prefer-global-this.js | 44 ++++++++++++++++++------------------- test/prefer-global-this.mjs | 8 +++---- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index a2b7f4b3ed..86b6329549 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -1,10 +1,10 @@ -"use strict"; +'use strict'; -const MESSAGE_ID_ERROR = "prefer-global-this/error"; -const MESSAGE_ID_SUGGESTION = "prefer-global-this/suggestion"; +const MESSAGE_ID_ERROR = 'prefer-global-this/error'; +const MESSAGE_ID_SUGGESTION = 'prefer-global-this/suggestion'; const messages = { - [MESSAGE_ID_ERROR]: "Prefer `{{replacement}}` over `{{value}}`.", - [MESSAGE_ID_SUGGESTION]: "Replace `{{value}}` with `{{replacement}}`.", + [MESSAGE_ID_ERROR]: 'Prefer `{{replacement}}` over `{{value}}`.', + [MESSAGE_ID_SUGGESTION]: 'Replace `{{value}}` with `{{replacement}}`.', }; /** @@ -14,11 +14,11 @@ const messages = { * @returns */ function findVariableInScope(scope, variableName) { - if (!scope || scope.type === "global") { + if (!scope || scope.type === 'global') { return undefined; } - const variable = scope.variables.find((v) => v.name === variableName); + const variable = scope.variables.find(v => v.name === variableName); if (variable) { return variable; @@ -28,9 +28,9 @@ function findVariableInScope(scope, variableName) { } /** @param {import('eslint').Rule.RuleContext} context */ -const create = (context) => ({ +const create = context => ({ Identifier(node) { - if (node.name !== "window" && node.name !== "global") { + if (node.name !== 'window' && node.name !== 'global') { return; } @@ -40,7 +40,7 @@ const create = (context) => ({ // Skip `window` and `global` in function declarations and variable declarations. if (parent) { - if (["FunctionDeclaration", "FunctionExpression"].includes(parent.type)) { + if (['FunctionDeclaration', 'FunctionExpression'].includes(parent.type)) { // Skip `function window() {}` and `function global() {}` if (parent.id === node) { return; @@ -55,16 +55,16 @@ const create = (context) => ({ } // Skip `var window = 1;` and `var global = 1;` - if (parent.type === "VariableDeclarator" && parent.id === node) { + if (parent.type === 'VariableDeclarator' && parent.id === node) { return; } // Skip `foo.window` and `foo.global`, but not allow `window.window` and `global.global if ( - parent.type === "MemberExpression" && - parent.property === node && - parent.object.type === "Identifier" && - parent.object.name !== node.name + parent.type === 'MemberExpression' + && parent.property === node + && parent.object.type === 'Identifier' + && parent.object.name !== node.name ) { return; } @@ -85,11 +85,11 @@ const create = (context) => ({ messageId: MESSAGE_ID_ERROR, data: { value: node.name, - replacement: "globalThis", + replacement: 'globalThis', }, /** @param {import('eslint').Rule.RuleFixer} fixer */ - fix: (fixer) => fixer.replaceText(node, "globalThis"), + fix: fixer => fixer.replaceText(node, 'globalThis'), /** @param {import('eslint').Rule.RuleFixer} fixer */ suggest: [ @@ -97,10 +97,10 @@ const create = (context) => ({ messageId: MESSAGE_ID_SUGGESTION, data: { value: node.name, - replacement: "globalThis", + replacement: 'globalThis', }, /** @param {import('eslint').Rule.RuleFixer} fixer */ - fix: (fixer) => fixer.replaceText(node, "globalThis"), + fix: fixer => fixer.replaceText(node, 'globalThis'), }, ], }; @@ -111,12 +111,12 @@ const create = (context) => ({ module.exports = { create, meta: { - type: "suggestion", + type: 'suggestion', docs: { - description: "Prefer `globalThis` instead of `window` and `global`.", + description: 'Prefer `globalThis` instead of `window` and `global`.', recommended: true, }, - fixable: "code", + fixable: 'code', hasSuggestions: true, messages, }, diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index fbbdc043a2..fea7773e7e 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -44,9 +44,9 @@ test.snapshot({ 'const { foo } = global', 'function foo() { window.foo() }', 'foo(window)', - "window.window", - "global.global", - "window.global", - "global.window", + 'window.window', + 'global.global', + 'window.global', + 'global.window', ], }); From f2c4c6afbd1c4da92dcf0f0cb9556631b4b382b3 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 14:05:43 +0800 Subject: [PATCH 04/70] test: add more test case --- rules/prefer-global-this.js | 4 +- test/prefer-global-this.mjs | 8 +- test/snapshots/prefer-global-this.mjs.md | 186 +++++++++++++++++++-- test/snapshots/prefer-global-this.mjs.snap | Bin 876 -> 1070 bytes 4 files changed, 178 insertions(+), 20 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 86b6329549..63d7a2182e 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -27,10 +27,12 @@ function findVariableInScope(scope, variableName) { return findVariableInScope(scope.upper, variableName); } +const globalIdentifier = new Set(['window', 'self', 'global']); + /** @param {import('eslint').Rule.RuleContext} context */ const create = context => ({ Identifier(node) { - if (node.name !== 'window' && node.name !== 'global') { + if (!globalIdentifier.has(node.name)) { return; } diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index fea7773e7e..15b4650c21 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -40,13 +40,19 @@ test.snapshot({ 'global.foo', 'global[foo]', 'global.foo()', + 'self', + 'self.foo', + 'self[foo]', + 'self.foo()', 'const { foo } = window', 'const { foo } = global', 'function foo() { window.foo() }', 'foo(window)', 'window.window', - 'global.global', 'window.global', + 'global.global', 'global.window', + 'self.window', + 'window.self', ], }); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 06d194e58c..99e046cf1d 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -204,7 +204,107 @@ Generated by [AVA](https://avajs.dev). 1 | globalThis.foo()␊ ` -## invalid(9): const { foo } = window +## invalid(9): self + +> Input + + `␊ + 1 | self␊ + ` + +> Output + + `␊ + 1 | globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | self␊ + | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ + 1 | globalThis␊ + ` + +## invalid(10): self.foo + +> Input + + `␊ + 1 | self.foo␊ + ` + +> Output + + `␊ + 1 | globalThis.foo␊ + ` + +> Error 1/1 + + `␊ + > 1 | self.foo␊ + | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ + 1 | globalThis.foo␊ + ` + +## invalid(11): self[foo] + +> Input + + `␊ + 1 | self[foo]␊ + ` + +> Output + + `␊ + 1 | globalThis[foo]␊ + ` + +> Error 1/1 + + `␊ + > 1 | self[foo]␊ + | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ + 1 | globalThis[foo]␊ + ` + +## invalid(12): self.foo() + +> Input + + `␊ + 1 | self.foo()␊ + ` + +> Output + + `␊ + 1 | globalThis.foo()␊ + ` + +> Error 1/1 + + `␊ + > 1 | self.foo()␊ + | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ + 1 | globalThis.foo()␊ + ` + +## invalid(13): const { foo } = window > Input @@ -229,7 +329,7 @@ Generated by [AVA](https://avajs.dev). 1 | const { foo } = globalThis␊ ` -## invalid(10): const { foo } = global +## invalid(14): const { foo } = global > Input @@ -254,7 +354,7 @@ Generated by [AVA](https://avajs.dev). 1 | const { foo } = globalThis␊ ` -## invalid(11): function foo() { window.foo() } +## invalid(15): function foo() { window.foo() } > Input @@ -279,7 +379,7 @@ Generated by [AVA](https://avajs.dev). 1 | function foo() { globalThis.foo() }␊ ` -## invalid(12): foo(window) +## invalid(16): foo(window) > Input @@ -304,7 +404,7 @@ Generated by [AVA](https://avajs.dev). 1 | foo(globalThis)␊ ` -## invalid(13): window.window +## invalid(17): window.window > Input @@ -340,7 +440,32 @@ Generated by [AVA](https://avajs.dev). 1 | window.globalThis␊ ` -## invalid(14): global.global +## invalid(18): window.global + +> Input + + `␊ + 1 | window.global␊ + ` + +> Output + + `␊ + 1 | globalThis.global␊ + ` + +> Error 1/1 + + `␊ + > 1 | window.global␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.global␊ + ` + +## invalid(19): global.global > Input @@ -376,37 +501,37 @@ Generated by [AVA](https://avajs.dev). 1 | global.globalThis␊ ` -## invalid(15): window.global +## invalid(20): global.window > Input `␊ - 1 | window.global␊ + 1 | global.window␊ ` > Output `␊ - 1 | globalThis.global␊ + 1 | globalThis.window␊ ` > Error 1/1 `␊ - > 1 | window.global␊ - | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + > 1 | global.window␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.global␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | globalThis.window␊ ` -## invalid(16): global.window +## invalid(21): self.window > Input `␊ - 1 | global.window␊ + 1 | self.window␊ ` > Output @@ -418,10 +543,35 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | global.window␊ - | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + > 1 | self.window␊ + | ^^^^ Prefer \`globalThis\` over \`self\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ 1 | globalThis.window␊ ` + +## invalid(22): window.self + +> Input + + `␊ + 1 | window.self␊ + ` + +> Output + + `␊ + 1 | globalThis.self␊ + ` + +> Error 1/1 + + `␊ + > 1 | window.self␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.self␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 181eaaa98d184f636bc9e5dc49510b4a06ec2f54..6113d6c2e3c2ca602f379fe1b03475d8b6947a21 100644 GIT binary patch literal 1070 zcmV+}1kw9JRzVk%ymlUiHY%39?d0?=92(TMe* z(;dCv9z&wUWYPU(uq;T-zIenX=k2C4-yQxTQp2kW$3YD2qo7XggL*gYDL3W239{b=V z-vN<#ERm>>q!WqKL8!rNIj5LU&D^; zp-p6BjJDBDX+LZlWPFSS6{|(WW`TZOqE~y(S8GX`u@$8u?73etu zXxXJS9%%U`b)cZZEjBUe19|$}1L$cA+V3`)EvMEA+}Q@uCTPB(ZJzi%AT~+n(c?8D z^h@AHQ?eIDcPjd_NDWMa8W;&`px4C2#gNivA3u4DJDldXKm5_%Z~_k&U$PlV{G*XC z3MVP{;6H%u*T93>cp=4b)xCjNpTQR7A({8+Gdf?ti(&oB&KAo0l^-d95#-Ow>UR&d zo2(0dAW_NEpxSDd!lqsnm3pfIq5*C-Fm6VgdtzKYwi;0;QhnY9Unt&IqtAx*E4!~M z>sM}-J+~SlO;WqbZ1Mo3QrIMa^wfinoD`J!=*dX>jcFHP`T!b09Hf+XfMVle{(K|; o1wr)}kFxBCgkDWkR+!)~9_7f73aK`0CIum&e`IB)_12M_`^ zZId=4imN1TCv7{yAHcuB{wIzIAvhs~5I1fpjpO*$c7C7{t;sR+*Ux#MXMdmb!RT7J z_r`sHpnIlg>5genG|TMQ)Os6DO}me$rfX{>cZfar?LohO?bk5T5vNg3+CZqTD>>M|nCP40P8sv5nLXwT+(WBTMV)G$xvw-Vm&* zA^ULif#YDupN3GFgcO>TLc_qACn3&kq!7`#1~limMKL-^nMp)!t^?6|ZfUF#!ubi{e1>oWSuyCaDd6zzR6;&mVCU58 zJfJGb^)k12YIPBz8$eYN77tZIM85!{FZ}+g)eFK1B!PoOJ*HJ}6H!`^2}b{Kk0DV~ zvIySf%Ywu_6py)0DP-}ONRfxfFwu%ZC6&kAp=2_73?s?KW7v4bpp(*L?t-0@-eXuz zJ{|)i7K2f|$Lv%?NZa)`>S5dU&@M7CM*HZV^kTCP5`Trn6stwxHi5n>(Z`$8i}EsH zxKt(#CCdnC&OeLUK_q61=e$BMteXPRvhE@sXnD7hD`?P;WCndCxA8xKUZV-gNfE;6U`q~bh5b`SOqmu32Pu}Vd7#~&~2YS zc`;_J`u|G&(Lp$Y8H>9mMv}f;@!TDCXIO$ zen;}Q0y2IU-pl3Qy9Q*J`FcU6o{s(%3?DG;VK9RL6u CWS#{8 From cdace671aec8aa370070ec5eb999be8e7500c9c5 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 14:08:35 +0800 Subject: [PATCH 05/70] fix: lint --- rules/prefer-global-this.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 63d7a2182e..72c8a98f77 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -15,7 +15,7 @@ const messages = { */ function findVariableInScope(scope, variableName) { if (!scope || scope.type === 'global') { - return undefined; + return; } const variable = scope.variables.find(v => v.name === variableName); From 77d99d491a85b43b45570192ecd6d8c197775732 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 14:22:10 +0800 Subject: [PATCH 06/70] add test for typescript --- rules/prefer-global-this.js | 5 +++++ test/prefer-global-this.mjs | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 72c8a98f77..72fc00ace2 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -70,6 +70,11 @@ const create = context => ({ ) { return; } + + // Skip `import window from "xxx"` + if (parent.type === 'ImportSpecifier' && parent.local === node) { + return; + } } const variable = findVariableInScope( diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 15b4650c21..bd240d2cb3 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -1,4 +1,4 @@ -import {getTester} from './utils/test.mjs'; +import {getTester, parsers} from './utils/test.mjs'; import outdent from 'outdent'; const {test} = getTester(import.meta); @@ -30,6 +30,7 @@ test.snapshot({ `, 'foo.window', 'foo.global', + 'import window from "xxx"', ], invalid: [ 'window', @@ -56,3 +57,16 @@ test.snapshot({ 'window.self', ], }); + +test.snapshot({ + testerOptions: { + languageOptions: {parser: parsers.typescript}, + }, + valid: [ + 'declare function window(): void;', + 'declare var window: any;', + ], + invalid: [ + + ], +}); From 957f54a8c12b383e8fef48de8b0c8a9e7eb5bcd6 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 15:07:34 +0800 Subject: [PATCH 07/70] add more test --- rules/prefer-global-this.js | 20 ++++++++++++++++++++ test/prefer-global-this.mjs | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 72fc00ace2..2ba0bbb683 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -75,6 +75,26 @@ const create = context => ({ if (parent.type === 'ImportSpecifier' && parent.local === node) { return; } + + // Skip `import * as window from "xxx"` + if (parent.type === 'ImportNamespaceSpecifier' && parent.local === node) { + return; + } + + // Skip `import window, {foo} from "xxx"` + if (parent.type === 'ImportDefaultSpecifier' && parent.local === node) { + return; + } + + // Skip `export { window } from "xxx"` + if (parent.type === 'ExportSpecifier' && parent.local === node) { + return; + } + + // Skip `export * as window from "xxx"` + if (parent.type === 'ExportAllDeclaration' && parent.exported === node) { + return; + } } const variable = findVariableInScope( diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index bd240d2cb3..1b9783da2a 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -31,6 +31,10 @@ test.snapshot({ 'foo.window', 'foo.global', 'import window from "xxx"', + 'import * as window from "xxx"', + 'import window, {foo} from "xxx"', + 'export { window } from "xxx"', + 'export * as window from "xxx";', ], invalid: [ 'window', From d7b725d97b100d0485e66ca270a166c134cd53a1 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 16:54:41 +0800 Subject: [PATCH 08/70] Re-implement prefer-global-this --- rules/prefer-global-this.js | 222 ++++++---- test/prefer-global-this.mjs | 80 ++-- test/snapshots/prefer-global-this.mjs.md | 488 +++++++++++++++------ test/snapshots/prefer-global-this.mjs.snap | Bin 1070 -> 1757 bytes 4 files changed, 536 insertions(+), 254 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 2ba0bbb683..5578e0c9b2 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -29,108 +29,150 @@ function findVariableInScope(scope, variableName) { const globalIdentifier = new Set(['window', 'self', 'global']); -/** @param {import('eslint').Rule.RuleContext} context */ -const create = context => ({ - Identifier(node) { - if (!globalIdentifier.has(node.name)) { - return; - } - - const ancestors = context.sourceCode.getAncestors(node); - - const parent = ancestors.length > 0 ? ancestors.at(-1) : undefined; - - // Skip `window` and `global` in function declarations and variable declarations. - if (parent) { - if (['FunctionDeclaration', 'FunctionExpression'].includes(parent.type)) { - // Skip `function window() {}` and `function global() {}` - if (parent.id === node) { - return; - } - - // Skip `function foo(window) {}` and `function foo(global) {}` - if (parent.params.includes(node)) { - return; - } - - return; - } - - // Skip `var window = 1;` and `var global = 1;` - if (parent.type === 'VariableDeclarator' && parent.id === node) { - return; - } +/** + * + * @param {import('eslint').Rule.RuleContext} context + * @param {import('estree').Node} node + * @param {string} value + */ +function report(context, node, value) { + context.report({ + node, + messageId: MESSAGE_ID_ERROR, + data: { + value, + replacement: 'globalThis', + }, + fix: fixer => fixer.replaceText(node, 'globalThis'), + suggest: [ + { + messageId: MESSAGE_ID_SUGGESTION, + data: { + value, + replacement: 'globalThis', + }, + fix: fixer => fixer.replaceText(node, 'globalThis'), + }, + ], + }); +} - // Skip `foo.window` and `foo.global`, but not allow `window.window` and `global.global - if ( - parent.type === 'MemberExpression' - && parent.property === node - && parent.object.type === 'Identifier' - && parent.object.name !== node.name - ) { - return; - } +/** + * + * @param {import('eslint').Rule.RuleContext} context + * @param {import('estree').Node | Array} nodes + * @returns + */ +function handleNodes(context, nodes) { + if (!Array.isArray(nodes)) { + nodes = [nodes]; + } - // Skip `import window from "xxx"` - if (parent.type === 'ImportSpecifier' && parent.local === node) { - return; - } + for (const node of nodes) { + if (node && node.type === 'Identifier' && globalIdentifier.has(node.name)) { + const variable = findVariableInScope( + context.sourceCode.getScope(node), + node.name, + ); - // Skip `import * as window from "xxx"` - if (parent.type === 'ImportNamespaceSpecifier' && parent.local === node) { + if (variable) { return; } - // Skip `import window, {foo} from "xxx"` - if (parent.type === 'ImportDefaultSpecifier' && parent.local === node) { - return; - } + return report(context, node, node.name); + } + } +} - // Skip `export { window } from "xxx"` - if (parent.type === 'ExportSpecifier' && parent.local === node) { - return; +/** @param {import('eslint').Rule.RuleContext} context */ +const create = context => ({ + /** @param {import('estree').MemberExpression} node */ + MemberExpression(node) { + handleNodes(context, [node.object]); + }, + /** @param {import('estree').CallExpression} node */ + CallExpression(node) { + handleNodes(context, [node.object]); + }, + /** @param {import('estree').BinaryExpression} node */ + BinaryExpression(node) { + handleNodes(context, [node.left, node.right]); + }, + /** @param {import('estree').LogicalExpression} node */ + LogicalExpression(node) { + handleNodes(context, [node.left, node.right]); + }, + /** @param {import('estree').ArrayExpression} node */ + ArrayExpression(node) { + handleNodes(context, node.elements); + }, + /** @param {import('estree').AssignmentExpression} node */ + AssignmentExpression(node) { + handleNodes(context, [node.left, node.right]); + }, + /** @param {import('estree').YieldExpression} node */ + YieldExpression(node) { + handleNodes(context, node.argument); + }, + /** @param {import('estree').AwaitExpression} node */ + AwaitExpression(node) { + handleNodes(context, node.argument); + }, + /** @param {import('estree').ConditionalExpression} node */ + ConditionalExpression(node) { + handleNodes(context, [node.test, node.consequent, node.alternate]); + }, + /** @param {import('estree').ExpressionStatement} node */ + ExpressionStatement(node) { + switch (node.expression.type) { + case 'Identifier': { + handleNodes(context, node.expression); + break; } - // Skip `export * as window from "xxx"` - if (parent.type === 'ExportAllDeclaration' && parent.exported === node) { - return; + default: { + break; } } - - const variable = findVariableInScope( - context.sourceCode.getScope(node), - node.name, - ); - - // Skip that has been declared in the scope - if (variable) { - return; + }, + /** @param {import('estree').ImportExpression} node */ + ImportExpression(node) { + handleNodes(context, node.source); + }, + /** @param {import('estree').ReturnStatement} node */ + ReturnStatement(node) { + handleNodes(context, node.argument); + }, + /** @param {import('estree').NewExpression} node */ + NewExpression(node) { + handleNodes(context, node.callee); + }, + /** @param {import('estree').ObjectExpression} node */ + ObjectExpression(node) { + for (const property of node.properties) { + handleNodes(context, property.value); } - - return { - node, - messageId: MESSAGE_ID_ERROR, - data: { - value: node.name, - replacement: 'globalThis', - }, - - /** @param {import('eslint').Rule.RuleFixer} fixer */ - fix: fixer => fixer.replaceText(node, 'globalThis'), - - /** @param {import('eslint').Rule.RuleFixer} fixer */ - suggest: [ - { - messageId: MESSAGE_ID_SUGGESTION, - data: { - value: node.name, - replacement: 'globalThis', - }, - /** @param {import('eslint').Rule.RuleFixer} fixer */ - fix: fixer => fixer.replaceText(node, 'globalThis'), - }, - ], - }; + }, + /** @param {import('estree').SequenceExpression} node */ + SequenceExpression(node) { + handleNodes(context, node.expressions); + }, + /** @param {import('estree').TaggedTemplateExpression} node */ + TaggedTemplateExpression(node) { + handleNodes(context, node.tag); + handleNodes(context, node.quasi.expressions); + }, + /** @param {import('estree').TemplateLiteral} node */ + TemplateLiteral(node) { + handleNodes(context, node.expressions); + }, + /** @param {import('estree').UnaryExpression} node */ + UnaryExpression(node) { + handleNodes(context, node.argument); + }, + /** @param {import('estree').UnaryExpression} node */ + UpdateExpression(node) { + handleNodes(context, node.argument); }, }); diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 1b9783da2a..e1bd000758 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -1,4 +1,4 @@ -import {getTester, parsers} from './utils/test.mjs'; +import {getTester} from './utils/test.mjs'; import outdent from 'outdent'; const {test} = getTester(import.meta); @@ -37,40 +37,58 @@ test.snapshot({ 'export * as window from "xxx";', ], invalid: [ + 'global', + 'self', 'window', 'window.foo', 'window[foo]', 'window.foo()', - 'global', - 'global.foo', - 'global[foo]', - 'global.foo()', - 'self', - 'self.foo', - 'self[foo]', - 'self.foo()', - 'const { foo } = window', - 'const { foo } = global', - 'function foo() { window.foo() }', - 'foo(window)', - 'window.window', - 'window.global', - 'global.global', - 'global.window', - 'self.window', - 'window.self', + 'window > 10', + '10 > window', + 'window ?? 10', + '10 ?? window', + 'window.foo = 123', + 'window = 123', + 'obj.a = window', + outdent` + function* gen() { + yield window + } + `, + outdent` + async function gen() { + await window + } + `, + 'window ? foo : bar', + 'foo ? window : bar', + 'foo ? bar : window', + outdent` + function foo() { + return window + } + `, + 'new window()', + outdent` + const obj = { + foo: window.foo, + bar: window.bar, + window: window + } + `, + outdent` + function sequenceTest() { + let x, y; + x = (y = 10, y + 5, window); + console.log(x, y); + } + `, + 'window`Hello ${42} World`', // eslint-disable-line no-template-curly-in-string + 'tag`Hello ${window.foo} World`', // eslint-disable-line no-template-curly-in-string + 'var str = `hello ${window.foo} world!`', // eslint-disable-line no-template-curly-in-string + 'delete window.foo', + '++window', + '++window.foo', ], }); -test.snapshot({ - testerOptions: { - languageOptions: {parser: parsers.typescript}, - }, - valid: [ - 'declare function window(): void;', - 'declare var window: any;', - ], - invalid: [ - - ], -}); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 99e046cf1d..8ccf566c6a 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -4,7 +4,57 @@ The actual snapshot is saved in `prefer-global-this.mjs.snap`. Generated by [AVA](https://avajs.dev). -## invalid(1): window +## invalid(1): global + +> Input + + `␊ + 1 | global␊ + ` + +> Output + + `␊ + 1 | globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | global␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ + 1 | globalThis␊ + ` + +## invalid(2): self + +> Input + + `␊ + 1 | self␊ + ` + +> Output + + `␊ + 1 | globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | self␊ + | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ + 1 | globalThis␊ + ` + +## invalid(3): window > Input @@ -29,7 +79,7 @@ Generated by [AVA](https://avajs.dev). 1 | globalThis␊ ` -## invalid(2): window.foo +## invalid(4): window.foo > Input @@ -54,7 +104,7 @@ Generated by [AVA](https://avajs.dev). 1 | globalThis.foo␊ ` -## invalid(3): window[foo] +## invalid(5): window[foo] > Input @@ -79,7 +129,7 @@ Generated by [AVA](https://avajs.dev). 1 | globalThis[foo]␊ ` -## invalid(4): window.foo() +## invalid(6): window.foo() > Input @@ -104,474 +154,646 @@ Generated by [AVA](https://avajs.dev). 1 | globalThis.foo()␊ ` -## invalid(5): global +## invalid(7): window > 10 > Input `␊ - 1 | global␊ + 1 | window > 10␊ ` > Output `␊ - 1 | globalThis␊ + 1 | globalThis > 10␊ ` > Error 1/1 `␊ - > 1 | global␊ - | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + > 1 | window > 10␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ - 1 | globalThis␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis > 10␊ ` -## invalid(6): global.foo +## invalid(8): 10 > window > Input `␊ - 1 | global.foo␊ + 1 | 10 > window␊ ` > Output `␊ - 1 | globalThis.foo␊ + 1 | 10 > globalThis␊ ` > Error 1/1 `␊ - > 1 | global.foo␊ - | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + > 1 | 10 > window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ - 1 | globalThis.foo␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | 10 > globalThis␊ ` -## invalid(7): global[foo] +## invalid(9): window ?? 10 > Input `␊ - 1 | global[foo]␊ + 1 | window ?? 10␊ ` > Output `␊ - 1 | globalThis[foo]␊ + 1 | globalThis ?? 10␊ ` > Error 1/1 `␊ - > 1 | global[foo]␊ - | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + > 1 | window ?? 10␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ - 1 | globalThis[foo]␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis ?? 10␊ ` -## invalid(8): global.foo() +## invalid(10): 10 ?? window > Input `␊ - 1 | global.foo()␊ + 1 | 10 ?? window␊ ` > Output `␊ - 1 | globalThis.foo()␊ + 1 | 10 ?? globalThis␊ ` > Error 1/1 `␊ - > 1 | global.foo()␊ - | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + > 1 | 10 ?? window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ - 1 | globalThis.foo()␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | 10 ?? globalThis␊ ` -## invalid(9): self +## invalid(11): window.foo = 123 > Input `␊ - 1 | self␊ + 1 | window.foo = 123␊ ` > Output `␊ - 1 | globalThis␊ + 1 | globalThis.foo = 123␊ ` > Error 1/1 `␊ - > 1 | self␊ - | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + > 1 | window.foo = 123␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ - 1 | globalThis␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.foo = 123␊ ` -## invalid(10): self.foo +## invalid(12): window = 123 > Input `␊ - 1 | self.foo␊ + 1 | window = 123␊ ` > Output `␊ - 1 | globalThis.foo␊ + 1 | globalThis = 123␊ ` > Error 1/1 `␊ - > 1 | self.foo␊ - | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + > 1 | window = 123␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ - 1 | globalThis.foo␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis = 123␊ ` -## invalid(11): self[foo] +## invalid(13): obj.a = window > Input `␊ - 1 | self[foo]␊ + 1 | obj.a = window␊ ` > Output `␊ - 1 | globalThis[foo]␊ + 1 | obj.a = globalThis␊ ` > Error 1/1 `␊ - > 1 | self[foo]␊ - | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + > 1 | obj.a = window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ - 1 | globalThis[foo]␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | obj.a = globalThis␊ ` -## invalid(12): self.foo() +## invalid(14): function* gen() { yield window } > Input `␊ - 1 | self.foo()␊ + 1 | function* gen() {␊ + 2 | yield window␊ + 3 | }␊ ` > Output `␊ - 1 | globalThis.foo()␊ + 1 | function* gen() {␊ + 2 | yield globalThis␊ + 3 | }␊ ` > Error 1/1 `␊ - > 1 | self.foo()␊ - | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + 1 | function* gen() {␊ + > 2 | yield window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 3 | }␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ - 1 | globalThis.foo()␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | function* gen() {␊ + 2 | yield globalThis␊ + 3 | }␊ ` -## invalid(13): const { foo } = window +## invalid(15): async function gen() { await window } > Input `␊ - 1 | const { foo } = window␊ + 1 | async function gen() {␊ + 2 | await window␊ + 3 | }␊ ` > Output `␊ - 1 | const { foo } = globalThis␊ + 1 | async function gen() {␊ + 2 | await globalThis␊ + 3 | }␊ ` > Error 1/1 `␊ - > 1 | const { foo } = window␊ - | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 1 | async function gen() {␊ + > 2 | await window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 3 | }␊ ␊ --------------------------------------------------------------------------------␊ Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | const { foo } = globalThis␊ + 1 | async function gen() {␊ + 2 | await globalThis␊ + 3 | }␊ ` -## invalid(14): const { foo } = global +## invalid(16): window ? foo : bar > Input `␊ - 1 | const { foo } = global␊ + 1 | window ? foo : bar␊ ` > Output `␊ - 1 | const { foo } = globalThis␊ + 1 | globalThis ? foo : bar␊ ` > Error 1/1 `␊ - > 1 | const { foo } = global␊ - | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + > 1 | window ? foo : bar␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ - 1 | const { foo } = globalThis␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis ? foo : bar␊ + ` + +## invalid(17): foo ? window : bar + +> Input + + `␊ + 1 | foo ? window : bar␊ + ` + +> Output + + `␊ + 1 | foo ? globalThis : bar␊ + ` + +> Error 1/1 + + `␊ + > 1 | foo ? window : bar␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | foo ? globalThis : bar␊ + ` + +## invalid(18): foo ? bar : window + +> Input + + `␊ + 1 | foo ? bar : window␊ + ` + +> Output + + `␊ + 1 | foo ? bar : globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | foo ? bar : window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | foo ? bar : globalThis␊ ` -## invalid(15): function foo() { window.foo() } +## invalid(19): function foo() { return window } > Input `␊ - 1 | function foo() { window.foo() }␊ + 1 | function foo() {␊ + 2 | return window␊ + 3 | }␊ ` > Output `␊ - 1 | function foo() { globalThis.foo() }␊ + 1 | function foo() {␊ + 2 | return globalThis␊ + 3 | }␊ ` > Error 1/1 `␊ - > 1 | function foo() { window.foo() }␊ - | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 1 | function foo() {␊ + > 2 | return window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 3 | }␊ ␊ --------------------------------------------------------------------------------␊ Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | function foo() { globalThis.foo() }␊ + 1 | function foo() {␊ + 2 | return globalThis␊ + 3 | }␊ ` -## invalid(16): foo(window) +## invalid(20): new window() > Input `␊ - 1 | foo(window)␊ + 1 | new window()␊ ` > Output `␊ - 1 | foo(globalThis)␊ + 1 | new globalThis()␊ ` > Error 1/1 `␊ - > 1 | foo(window)␊ + > 1 | new window()␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | foo(globalThis)␊ + 1 | new globalThis()␊ ` -## invalid(17): window.window +## invalid(21): const obj = { foo: window.foo, bar: window.bar, window: window } > Input `␊ - 1 | window.window␊ + 1 | const obj = {␊ + 2 | foo: window.foo,␊ + 3 | bar: window.bar,␊ + 4 | window: window␊ + 5 | }␊ ` > Output `␊ - 1 | globalThis.globalThis␊ + 1 | const obj = {␊ + 2 | foo: globalThis.foo,␊ + 3 | bar: globalThis.bar,␊ + 4 | window: globalThis␊ + 5 | }␊ ` -> Error 1/2 +> Error 1/3 `␊ - > 1 | window.window␊ - | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 1 | const obj = {␊ + > 2 | foo: window.foo,␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 3 | bar: window.bar,␊ + 4 | window: window␊ + 5 | }␊ ␊ --------------------------------------------------------------------------------␊ Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.window␊ + 1 | const obj = {␊ + 2 | foo: globalThis.foo,␊ + 3 | bar: window.bar,␊ + 4 | window: window␊ + 5 | }␊ ` -> Error 2/2 +> Error 2/3 `␊ - > 1 | window.window␊ - | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 1 | const obj = {␊ + 2 | foo: window.foo,␊ + > 3 | bar: window.bar,␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 4 | window: window␊ + 5 | }␊ ␊ --------------------------------------------------------------------------------␊ Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | window.globalThis␊ + 1 | const obj = {␊ + 2 | foo: window.foo,␊ + 3 | bar: globalThis.bar,␊ + 4 | window: window␊ + 5 | }␊ ` -## invalid(18): window.global +> Error 3/3 + + `␊ + 1 | const obj = {␊ + 2 | foo: window.foo,␊ + 3 | bar: window.bar,␊ + > 4 | window: window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 5 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | const obj = {␊ + 2 | foo: window.foo,␊ + 3 | bar: window.bar,␊ + 4 | window: globalThis␊ + 5 | }␊ + ` + +## invalid(22): function sequenceTest() { let x, y; x = (y = 10, y + 5, window); console.log(x, y); } + +> Input + + `␊ + 1 | function sequenceTest() {␊ + 2 | let x, y;␊ + 3 | x = (y = 10, y + 5, window);␊ + 4 | console.log(x, y);␊ + 5 | }␊ + ` + +> Output + + `␊ + 1 | function sequenceTest() {␊ + 2 | let x, y;␊ + 3 | x = (y = 10, y + 5, globalThis);␊ + 4 | console.log(x, y);␊ + 5 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function sequenceTest() {␊ + 2 | let x, y;␊ + > 3 | x = (y = 10, y + 5, window);␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 4 | console.log(x, y);␊ + 5 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | function sequenceTest() {␊ + 2 | let x, y;␊ + 3 | x = (y = 10, y + 5, globalThis);␊ + 4 | console.log(x, y);␊ + 5 | }␊ + ` + +## invalid(23): window`Hello ${42} World` > Input `␊ - 1 | window.global␊ + 1 | window\`Hello ${42} World\`␊ ` > Output `␊ - 1 | globalThis.global␊ + 1 | globalThis\`Hello ${42} World\`␊ ` > Error 1/1 `␊ - > 1 | window.global␊ + > 1 | window\`Hello ${42} World\`␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.global␊ + 1 | globalThis\`Hello ${42} World\`␊ ` -## invalid(19): global.global +## invalid(24): tag`Hello ${window.foo} World` > Input `␊ - 1 | global.global␊ + 1 | tag\`Hello ${window.foo} World\`␊ ` > Output `␊ - 1 | globalThis.globalThis␊ + 1 | tag\`Hello ${globalThis.foo} World\`␊ ` -> Error 1/2 +> Error 1/1 `␊ - > 1 | global.global␊ - | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + > 1 | tag\`Hello ${window.foo} World\`␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ - 1 | globalThis.global␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | tag\`Hello ${globalThis.foo} World\`␊ + ` + +## invalid(25): var str = `hello ${window.foo} world!` + +> Input + + `␊ + 1 | var str = \`hello ${window.foo} world!\`␊ ` -> Error 2/2 +> Output `␊ - > 1 | global.global␊ - | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + 1 | var str = \`hello ${globalThis.foo} world!\`␊ + ` + +> Error 1/1 + + `␊ + > 1 | var str = \`hello ${window.foo} world!\`␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ - 1 | global.globalThis␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | var str = \`hello ${globalThis.foo} world!\`␊ ` -## invalid(20): global.window +## invalid(26): delete window.foo > Input `␊ - 1 | global.window␊ + 1 | delete window.foo␊ ` > Output `␊ - 1 | globalThis.window␊ + 1 | delete globalThis.foo␊ ` > Error 1/1 `␊ - > 1 | global.window␊ - | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + > 1 | delete window.foo␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ - 1 | globalThis.window␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | delete globalThis.foo␊ ` -## invalid(21): self.window +## invalid(27): ++window > Input `␊ - 1 | self.window␊ + 1 | ++window␊ ` > Output `␊ - 1 | globalThis.window␊ + 1 | ++globalThis␊ ` > Error 1/1 `␊ - > 1 | self.window␊ - | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + > 1 | ++window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ - 1 | globalThis.window␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | ++globalThis␊ ` -## invalid(22): window.self +## invalid(28): ++window.foo > Input `␊ - 1 | window.self␊ + 1 | ++window.foo␊ ` > Output `␊ - 1 | globalThis.self␊ + 1 | ++globalThis.foo␊ ` > Error 1/1 `␊ - > 1 | window.self␊ - | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + > 1 | ++window.foo␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ␊ --------------------------------------------------------------------------------␊ Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.self␊ + 1 | ++globalThis.foo␊ ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 6113d6c2e3c2ca602f379fe1b03475d8b6947a21..488916f5940f1b0b59bc4b06c8199cfcc9b8b947 100644 GIT binary patch literal 1757 zcmV<31|s=ERzVI&oH1S3I?E!Ew$ zzjSMgL?4R?00000000Bsn@evSRTRhLA_TDzqJW?+X*fY`u;aXJ=T!$gEC98O3IvrP zLLiUrYsWD1q~md%D9H*HA=XH+r5}WE&?PHC2vLMU1)&xp5G>HOXYSlH_u&~Qlz6svjdd0M=@3%jjxJjI*V-maB+A+*#EtO3dpkZ1S!)&%&#&&zla@rr< ztkn$1cx&Q;v4_U!C-LCe>BOT+fGixiS0{;SRESBgw6;5rdp)4*A4k_;+iJF5oBFFA z$2Ypo8=d-cELq~C0011oyS)#*W|KOxq3nAsgSF#-Q=U&I=Z^W4e52E7khasbT994H z7T|TVZ5ma=VnVm+Y@wXyRX5&z*|sg4x^XFNdlYi%0$#97=HaV)u&h9-`e*g9;Nb3|M_$Qy3JP2>W0;S|LXr*|8A6!`tM(Te;K$jk3wO` zqp-v%%-1bTBq6V?Zy}>`0ognyB*ocbB6kpxZ!nRbRXnJ01rW$|Ju=IT%-eO#dPhVv zh06Q{Len#mvAKwho)%K$4KbWw5u9%^oW5B+=

F@a&%P_^hDLNu@kj#QsU8W5Ng(LES^Ej1iO|yBMv9dM3m45N{Zvhx%sm;KP?d zjb|-gfb1fal=}cV9?m2@o}STw9l=eCE3kJrc3`-~vfd*-%(y$MEO=8wOJs*lBUqVDy+yn$aNq}6h zth~P@Kpqa@P)7PP@>>Y$m%Cx?8!2Hk@dA>KRpy@Q$>OiAw*JF87X==R<&Afhdx6>5%#GL`17(^I!o9W6~mr&|6Pzwg&S_MuOm)XH$4=` z)!BG3oU5|&VALeQ68#P^2o(S;iO6JCLq-$lIq|12u|iD9w%|? z`iPt}j5B=)<@i4>?K5M+Ra4oMMiuL`I(XU!TUQscJ#~HQ>POy_5o?d<oE^i4wqrvP%3G4Mb*Zl@i73zuwuF~fIBzm>yomhe)c%5Zi+u(}vWi5K z@skwEb8 zdJBUX9C02^wz{$i7(0w2eLs`QsE+a{5rN0tP~P=2X7W?MOlH6jH-1K>zVb-1NFJck zWFxtK-C61y$3)&#sw(UINq&~fC#U?6BX<#>?}L0$6OBG2Y3uw8?`7irX*d7?&;?hU literal 1070 zcmV+}1kw9JRzVk%ymlUiHY%39?d0?=92(TMe* z(;dCv9z&wUWYPU(uq;T-zIenX=k2C4-yQxTQp2kW$3YD2qo7XggL*gYDL3W239{b=V z-vN<#ERm>>q!WqKL8!rNIj5LU&D^; zp-p6BjJDBDX+LZlWPFSS6{|(WW`TZOqE~y(S8GX`u@$8u?73etu zXxXJS9%%U`b)cZZEjBUe19|$}1L$cA+V3`)EvMEA+}Q@uCTPB(ZJzi%AT~+n(c?8D z^h@AHQ?eIDcPjd_NDWMa8W;&`px4C2#gNivA3u4DJDldXKm5_%Z~_k&U$PlV{G*XC z3MVP{;6H%u*T93>cp=4b)xCjNpTQR7A({8+Gdf?ti(&oB&KAo0l^-d95#-Ow>UR&d zo2(0dAW_NEpxSDd!lqsnm3pfIq5*C-Fm6VgdtzKYwi;0;QhnY9Unt&IqtAx*E4!~M z>sM}-J+~SlO;WqbZ1Mo3QrIMa^wfinoD`J!=*dX>jcFHP`T!b09Hf+XfMVle{(K|; o1wr)}kFxBCgkDWkR+!)~9_7f73aK`0CIum&e Date: Fri, 26 Jul 2024 17:08:24 +0800 Subject: [PATCH 09/70] fix: report multiple nodes --- rules/prefer-global-this.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 5578e0c9b2..1f5ad14ff9 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -79,7 +79,7 @@ function handleNodes(context, nodes) { return; } - return report(context, node, node.name); + report(context, node, node.name); } } } @@ -170,7 +170,7 @@ const create = context => ({ UnaryExpression(node) { handleNodes(context, node.argument); }, - /** @param {import('estree').UnaryExpression} node */ + /** @param {import('estree').UpdateExpression} node */ UpdateExpression(node) { handleNodes(context, node.argument); }, From fc0a9bebfa5cea2a58ce9c71cb5124a0d3dd4758 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 18:13:36 +0800 Subject: [PATCH 10/70] Support more statement and add test case --- rules/prefer-global-this.js | 92 ++++- test/prefer-global-this.mjs | 51 +++ test/snapshots/prefer-global-this.mjs.md | 400 +++++++++++++++++++++ test/snapshots/prefer-global-this.mjs.snap | Bin 1757 -> 2473 bytes 4 files changed, 526 insertions(+), 17 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 1f5ad14ff9..11d53df912 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -86,6 +86,8 @@ function handleNodes(context, nodes) { /** @param {import('eslint').Rule.RuleContext} context */ const create = context => ({ + // ===== Expression ===== + /** @param {import('estree').MemberExpression} node */ MemberExpression(node) { handleNodes(context, [node.object]); @@ -122,27 +124,10 @@ const create = context => ({ ConditionalExpression(node) { handleNodes(context, [node.test, node.consequent, node.alternate]); }, - /** @param {import('estree').ExpressionStatement} node */ - ExpressionStatement(node) { - switch (node.expression.type) { - case 'Identifier': { - handleNodes(context, node.expression); - break; - } - - default: { - break; - } - } - }, /** @param {import('estree').ImportExpression} node */ ImportExpression(node) { handleNodes(context, node.source); }, - /** @param {import('estree').ReturnStatement} node */ - ReturnStatement(node) { - handleNodes(context, node.argument); - }, /** @param {import('estree').NewExpression} node */ NewExpression(node) { handleNodes(context, node.callee); @@ -174,6 +159,79 @@ const create = context => ({ UpdateExpression(node) { handleNodes(context, node.argument); }, + + // ===== Statements ===== + + /** @param {import('estree').ExpressionStatement} node */ + ExpressionStatement(node) { + switch (node.expression.type) { + case 'Identifier': { + handleNodes(context, node.expression); + break; + } + + default: { + break; + } + } + }, + /** @param {import('estree').ForStatement} node */ + ForStatement(node) { + handleNodes(context, [node.init, node.test, node.update]); + }, + /** @param {import('estree').ForInStatement} node */ + ForInStatement(node) { + handleNodes(context, [node.left, node.right]); + }, + /** @param {import('estree').ForOfStatement} node */ + ForOfStatement(node) { + handleNodes(context, [node.left, node.right]); + }, + /** @param {import('estree').ReturnStatement} node */ + ReturnStatement(node) { + handleNodes(context, node.argument); + }, + /** @param {import('estree').SwitchStatement} node */ + SwitchStatement(node) { + handleNodes(context, node.discriminant); + + for (const caseNode of node.cases) { + handleNodes(context, caseNode.test); + } + }, + /** @param {import('estree').WhileStatement} node */ + WhileStatement(node) { + handleNodes(context, node.test); + }, + /** @param {import('estree').DoWhileStatement} node */ + DoWhileStatement(node) { + handleNodes(context, node.test); + }, + /** @param {import('estree').IfStatement} node */ + IfStatement(node) { + handleNodes(context, node.test); + }, + /** @param {import('estree').ThrowStatement} node */ + ThrowStatement(node) { + handleNodes(context, node.argument); + }, + /** @param {import('estree').TryStatement} node */ + TryStatement(_node) {}, + /** @param {import('estree').CatchClause} node */ + CatchClause(node) { + handleNodes(context, node.param); + }, + + // ===== Declarations ===== + + /** @param {import('estree').VariableDeclarator} node */ + VariableDeclarator(node) { + handleNodes(context, node.init); + }, + /** @param {import('estree').AssignmentPattern} node */ + AssignmentPattern(node) { + handleNodes(context, node.right); + }, }); /** @type {import('eslint').Rule.RuleModule} */ diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index e1bd000758..e57b322165 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -89,6 +89,57 @@ test.snapshot({ 'delete window.foo', '++window', '++window.foo', + outdent` + for (var attr in window) { + + } + `, + outdent` + for (window.foo = 0; i < 10; window.foo++) { + + } + `, + outdent` + for (const item of window.foo) { + } + `, + outdent` + for (const item of window) { + } + `, + outdent` + switch (window) {} + `, + outdent` + switch (true) { + case window: + break; + } + `, + outdent` + switch (true) { + case window.foo: + break; + } + `, + outdent` + while (window) { + } + `, + 'do {} while (window) {}', + 'if (window) {}', + 'throw window', + // Outdent` + // try { + + // } catch (window) {} + // `, + 'var foo = window', + outdent` + function foo (name = window) { + + } + `, ], }); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 8ccf566c6a..08369cdeea 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -797,3 +797,403 @@ Generated by [AVA](https://avajs.dev). Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ 1 | ++globalThis.foo␊ ` + +## invalid(29): for (var attr in window) { } + +> Input + + `␊ + 1 | for (var attr in window) {␊ + 2 |␊ + 3 | }␊ + ` + +> Output + + `␊ + 1 | for (var attr in globalThis) {␊ + 2 |␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | for (var attr in window) {␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 2 |␊ + 3 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | for (var attr in globalThis) {␊ + 2 |␊ + 3 | }␊ + ` + +## invalid(30): for (window.foo = 0; i < 10; window.foo++) { } + +> Input + + `␊ + 1 | for (window.foo = 0; i < 10; window.foo++) {␊ + 2 |␊ + 3 | }␊ + ` + +> Output + + `␊ + 1 | for (globalThis.foo = 0; i < 10; globalThis.foo++) {␊ + 2 |␊ + 3 | }␊ + ` + +> Error 1/2 + + `␊ + > 1 | for (window.foo = 0; i < 10; window.foo++) {␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 2 |␊ + 3 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | for (globalThis.foo = 0; i < 10; window.foo++) {␊ + 2 |␊ + 3 | }␊ + ` + +> Error 2/2 + + `␊ + > 1 | for (window.foo = 0; i < 10; window.foo++) {␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 2 |␊ + 3 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | for (window.foo = 0; i < 10; globalThis.foo++) {␊ + 2 |␊ + 3 | }␊ + ` + +## invalid(31): for (const item of window.foo) { } + +> Input + + `␊ + 1 | for (const item of window.foo) {␊ + 2 | }␊ + ` + +> Output + + `␊ + 1 | for (const item of globalThis.foo) {␊ + 2 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | for (const item of window.foo) {␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 2 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | for (const item of globalThis.foo) {␊ + 2 | }␊ + ` + +## invalid(32): for (const item of window) { } + +> Input + + `␊ + 1 | for (const item of window) {␊ + 2 | }␊ + ` + +> Output + + `␊ + 1 | for (const item of globalThis) {␊ + 2 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | for (const item of window) {␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 2 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | for (const item of globalThis) {␊ + 2 | }␊ + ` + +## invalid(33): switch (window) {} + +> Input + + `␊ + 1 | switch (window) {}␊ + ` + +> Output + + `␊ + 1 | switch (globalThis) {}␊ + ` + +> Error 1/1 + + `␊ + > 1 | switch (window) {}␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | switch (globalThis) {}␊ + ` + +## invalid(34): switch (true) { case window: break; } + +> Input + + `␊ + 1 | switch (true) {␊ + 2 | case window:␊ + 3 | break;␊ + 4 | }␊ + ` + +> Output + + `␊ + 1 | switch (true) {␊ + 2 | case globalThis:␊ + 3 | break;␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | switch (true) {␊ + > 2 | case window:␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 3 | break;␊ + 4 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | switch (true) {␊ + 2 | case globalThis:␊ + 3 | break;␊ + 4 | }␊ + ` + +## invalid(35): switch (true) { case window.foo: break; } + +> Input + + `␊ + 1 | switch (true) {␊ + 2 | case window.foo:␊ + 3 | break;␊ + 4 | }␊ + ` + +> Output + + `␊ + 1 | switch (true) {␊ + 2 | case globalThis.foo:␊ + 3 | break;␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | switch (true) {␊ + > 2 | case window.foo:␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 3 | break;␊ + 4 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | switch (true) {␊ + 2 | case globalThis.foo:␊ + 3 | break;␊ + 4 | }␊ + ` + +## invalid(36): while (window) { } + +> Input + + `␊ + 1 | while (window) {␊ + 2 | }␊ + ` + +> Output + + `␊ + 1 | while (globalThis) {␊ + 2 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | while (window) {␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 2 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | while (globalThis) {␊ + 2 | }␊ + ` + +## invalid(37): do {} while (window) {} + +> Input + + `␊ + 1 | do {} while (window) {}␊ + ` + +> Output + + `␊ + 1 | do {} while (globalThis) {}␊ + ` + +> Error 1/1 + + `␊ + > 1 | do {} while (window) {}␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | do {} while (globalThis) {}␊ + ` + +## invalid(38): if (window) {} + +> Input + + `␊ + 1 | if (window) {}␊ + ` + +> Output + + `␊ + 1 | if (globalThis) {}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if (window) {}␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | if (globalThis) {}␊ + ` + +## invalid(39): throw window + +> Input + + `␊ + 1 | throw window␊ + ` + +> Output + + `␊ + 1 | throw globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | throw window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | throw globalThis␊ + ` + +## invalid(40): var foo = window + +> Input + + `␊ + 1 | var foo = window␊ + ` + +> Output + + `␊ + 1 | var foo = globalThis␊ + ` + +> Error 1/1 + + `␊ + > 1 | var foo = window␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | var foo = globalThis␊ + ` + +## invalid(41): function foo (name = window) { } + +> Input + + `␊ + 1 | function foo (name = window) {␊ + 2 |␊ + 3 | }␊ + ` + +> Output + + `␊ + 1 | function foo (name = globalThis) {␊ + 2 |␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | function foo (name = window) {␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + 2 |␊ + 3 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | function foo (name = globalThis) {␊ + 2 |␊ + 3 | }␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 488916f5940f1b0b59bc4b06c8199cfcc9b8b947..7920b68790e8e54e13e27a2090cb3da992a439d3 100644 GIT binary patch literal 2473 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 nCUss@A4Z)(VwhmI&oH1S3I?E!Ew$ zzjSMgL?4R?00000000Bsn@evSRTRhLA_TDzqJW?+X*fY`u;aXJ=T!$gEC98O3IvrP zLLiUrYsWD1q~md%D9H*HA=XH+r5}WE&?PHC2vLMU1)&xp5G>HOXYSlH_u&~Qlz6svjdd0M=@3%jjxJjI*V-maB+A+*#EtO3dpkZ1S!)&%&#&&zla@rr< ztkn$1cx&Q;v4_U!C-LCe>BOT+fGixiS0{;SRESBgw6;5rdp)4*A4k_;+iJF5oBFFA z$2Ypo8=d-cELq~C0011oyS)#*W|KOxq3nAsgSF#-Q=U&I=Z^W4e52E7khasbT994H z7T|TVZ5ma=VnVm+Y@wXyRX5&z*|sg4x^XFNdlYi%0$#97=HaV)u&h9-`e*g9;Nb3|M_$Qy3JP2>W0;S|LXr*|8A6!`tM(Te;K$jk3wO` zqp-v%%-1bTBq6V?Zy}>`0ognyB*ocbB6kpxZ!nRbRXnJ01rW$|Ju=IT%-eO#dPhVv zh06Q{Len#mvAKwho)%K$4KbWw5u9%^oW5B+=

F@a&%P_^hDLNu@kj#QsU8W5Ng(LES^Ej1iO|yBMv9dM3m45N{Zvhx%sm;KP?d zjb|-gfb1fal=}cV9?m2@o}STw9l=eCE3kJrc3`-~vfd*-%(y$MEO=8wOJs*lBUqVDy+yn$aNq}6h zth~P@Kpqa@P)7PP@>>Y$m%Cx?8!2Hk@dA>KRpy@Q$>OiAw*JF87X==R<&Afhdx6>5%#GL`17(^I!o9W6~mr&|6Pzwg&S_MuOm)XH$4=` z)!BG3oU5|&VALeQ68#P^2o(S;iO6JCLq-$lIq|12u|iD9w%|? z`iPt}j5B=)<@i4>?K5M+Ra4oMMiuL`I(XU!TUQscJ#~HQ>POy_5o?d<oE^i4wqrvP%3G4Mb*Zl@i73zuwuF~fIBzm>yomhe)c%5Zi+u(}vWi5K z@skwEb8 zdJBUX9C02^wz{$i7(0w2eLs`QsE+a{5rN0tP~P=2X7W?MOlH6jH-1K>zVb-1NFJck zWFxtK-C61y$3)&#sw(UINq&~fC#U?6BX<#>?}L0$6OBG2Y3uw8?`7irX*d7?&;?hU From 6021d482ae589f113aae1b9b9c3470924b4d415f Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 26 Jul 2024 18:20:43 +0800 Subject: [PATCH 11/70] docs: update description --- docs/rules/prefer-global-this.md | 2 +- readme.md | 2 +- rules/prefer-global-this.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index d556e85ecb..52f6c52fe0 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -1,4 +1,4 @@ -# Prefer `globalThis` instead of `window` and `global` +# Prefer `globalThis` instead of `window`, `self` and `global` 💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs-eslintconfigjs). diff --git a/readme.md b/readme.md index fbcc4aef10..0dee448e13 100644 --- a/readme.md +++ b/readme.md @@ -189,7 +189,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c | [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. | ✅ | | 💡 | | [prefer-event-target](docs/rules/prefer-event-target.md) | Prefer `EventTarget` over `EventEmitter`. | ✅ | | | | [prefer-export-from](docs/rules/prefer-export-from.md) | Prefer `export…from` when re-exporting. | ✅ | 🔧 | 💡 | -| [prefer-global-this](docs/rules/prefer-global-this.md) | Prefer `globalThis` instead of `window` and `global`. | ✅ | 🔧 | 💡 | +| [prefer-global-this](docs/rules/prefer-global-this.md) | Prefer `globalThis` instead of `window`, `self` and `global`. | ✅ | 🔧 | 💡 | | [prefer-includes](docs/rules/prefer-includes.md) | Prefer `.includes()` over `.indexOf()`, `.lastIndexOf()`, and `Array#some()` when checking for existence or non-existence. | ✅ | 🔧 | 💡 | | [prefer-json-parse-buffer](docs/rules/prefer-json-parse-buffer.md) | Prefer reading a JSON file as a buffer. | | 🔧 | | | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | ✅ | 🔧 | | diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 11d53df912..3639a473a1 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -240,7 +240,7 @@ module.exports = { meta: { type: 'suggestion', docs: { - description: 'Prefer `globalThis` instead of `window` and `global`.', + description: 'Prefer `globalThis` instead of `window`, `self` and `global`.', recommended: true, }, fixable: 'code', From b91e84056af6d74bfd61e942a7777b817b4f9d7e Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 29 Jul 2024 09:24:18 +0800 Subject: [PATCH 12/70] fix: Allows access to window/worker platform-specific APIs directly --- rules/prefer-global-this.js | 244 +++++++++++++++++++++ test/prefer-global-this.mjs | 12 + test/snapshots/prefer-global-this.mjs.md | 50 +++++ test/snapshots/prefer-global-this.mjs.snap | Bin 2473 -> 2555 bytes 4 files changed, 306 insertions(+) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 3639a473a1..eba905d811 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -29,6 +29,237 @@ function findVariableInScope(scope, variableName) { const globalIdentifier = new Set(['window', 'self', 'global']); +const windowSpecificAPIs = new Set([ + // Refs: https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-window-object + // Properties and methods + 'window', + 'self', + 'document', + 'name', + 'location', + 'history', + 'navigation', + 'customElements', + 'locationbar', + 'menubar', + 'personalbar', + 'scrollbars', + 'statusbar', + 'toolbar', + 'status', + 'close', + 'closed', + 'stop', + 'focus', + 'blur', + 'frames', + 'length', + 'top', + 'opener', + 'parent', + 'frameElement', + 'open', + 'object', + 'navigator', + 'clientInformation', + 'originAgentCluster', + 'alert', + 'confirm', + 'prompt', + 'print', + 'postMessage', + + // global events + 'onabort', + 'onauxclick', + 'onbeforeinput', + 'onbeforematch', + 'onbeforetoggle', + 'onblur', + 'oncancel', + 'oncanplay', + 'oncanplaythrough', + 'onchange', + 'onclick', + 'onclose', + 'oncontextlost', + 'oncontextmenu', + 'oncontextrestored', + 'oncopy', + 'oncuechange', + 'oncut', + 'ondblclick', + 'ondrag', + 'ondragend', + 'ondragenter', + 'ondragleave', + 'ondragover', + 'ondragstart', + 'ondrop', + 'ondurationchange', + 'onemptied', + 'onended', + 'onerror', + 'onfocus', + 'onformdata', + 'oninput', + 'oninvalid', + 'onkeydown', + 'onkeypress', + 'onkeyup', + 'onload', + 'onloadeddata', + 'onloadedmetadata', + 'onloadstart', + 'onmousedown', + 'onmouseenter', + 'onmouseleave', + 'onmousemove', + 'onmouseout', + 'onmouseover', + 'onmouseup', + 'onpaste', + 'onpause', + 'onplay', + 'onplaying', + 'onprogress', + 'onratechange', + 'onreset', + 'onresize', + 'onscroll', + 'onscrollend', + 'onsecuritypolicyviolation', + 'onseeked', + 'onseeking', + 'onselect', + 'onslotchange', + 'onstalled', + 'onsubmit', + 'onsuspend', + 'ontimeupdate', + 'ontoggle', + 'onvolumechange', + 'onwaiting', + 'onwebkitanimationend', + 'onwebkitanimationiteration', + 'onwebkitanimationstart', + 'onwebkittransitionend', + 'onwheel', + + // Window events + 'onafterprint', + 'onbeforeprint', + 'onbeforeunload', + 'onhashchange', + 'onlanguagechange', + 'onmessage', + 'onmessageerror', + 'onoffline', + 'ononline', + 'onpagehide', + 'onpagereveal', + 'onpageshow', + 'onpageswap', + 'onpopstate', + 'onrejectionhandled', + 'onstorage', + 'onunhandledrejection', + 'onunload', + + // Refs: https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow + 'addEventListener', + 'removeEventListener', + 'dispatchEvent', + + // Refs: https://dom.spec.whatwg.org/#idl-index + 'Event', + 'event', + 'CustomEvent', + 'EventTarget', + 'AbortController', + 'AbortSignal', + 'NodeList', + 'HTMLCollection', + 'MutationObserver', + 'MutationRecord', + 'EventTarget', + 'Document', + 'XMLDocument', + 'DOMImplementation', + 'DocumentType', + 'DocumentFragment', + 'ShadowRoot', + 'Element', + 'NamedNodeMap', + 'Attr', + 'CharacterData', + 'Text', + 'CDATASection', + 'ProcessingInstruction', + 'Comment', + 'AbstractRange', + 'StaticRange', + 'Range', + 'NodeIterator', + 'TreeWalker', + 'NodeFilter', + 'DOMTokenList', + 'XPathResult', + 'XPathExpression', + 'XPathEvaluator', + 'XSLTProcessor', + + // Refs: https://www.w3.org/TR/window-management/#usage-overview + 'screen', + 'getScreenDetails', + + // Refs: https://drafts.csswg.org/cssom-view/#extensions-to-the-window-interface + 'matchMedia', + 'visualViewport', + 'moveTo', + 'moveBy', + 'resizeTo', + 'resizeBy', + 'innerWidth', + 'innerHeight', + 'scrollX', + 'pageXOffset', + 'scrollY', + 'pageYOffset', + 'scroll', + 'scrollTo', + 'scrollBy', + 'screenX', + 'screenLeft', + 'screenY', + 'screenTop', + 'screenWidth', + 'screenHeight', + 'devicePixelRatio', +]); + +const webWorkerSpecificAPIs = new Set([ + // Refs: https://html.spec.whatwg.org/multipage/workers.html#the-workerglobalscope-common-interface + 'addEventListener', + 'removeEventListener', + 'dispatchEvent', + + 'self', + 'location', + 'navigator', + 'onerror', + 'onlanguagechange', + 'onoffline', + 'ononline', + 'onrejectionhandled', + 'onunhandledrejection', + + // Refs: https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-dedicatedworkerglobalscope-interface + 'name', + 'postMessage', + 'onconnect', +]); + /** * * @param {import('eslint').Rule.RuleContext} context @@ -90,6 +321,19 @@ const create = context => ({ /** @param {import('estree').MemberExpression} node */ MemberExpression(node) { + // Allow to use window specify APIs + if (node.object.type === 'Identifier') { + // Check if the identifier is a window specific API + if (node.object.name === 'window' && node.property.type === 'Identifier' && windowSpecificAPIs.has(node.property.name)) { + return; + } + + // Check if the identifier is a web worker specific API + if (node.object.name === 'self' && node.property.type === 'Identifier' && webWorkerSpecificAPIs.has(node.property.name)) { + return; + } + } + handleNodes(context, [node.object]); }, /** @param {import('estree').CallExpression} node */ diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index e57b322165..15a37c36a4 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -35,6 +35,16 @@ test.snapshot({ 'import window, {foo} from "xxx"', 'export { window } from "xxx"', 'export * as window from "xxx";', + + // Use window specify apis + 'window.name = "foo"', + 'window.alert()', + 'var doc = window.document', + 'window.addEventListener', + 'window.innerWidth', + 'window.innerHeight', + 'self.location', + 'self.navigator', ], invalid: [ 'global', @@ -140,6 +150,8 @@ test.snapshot({ } `, + 'self.innerWidth', + 'self.innerHeight', ], }); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 08369cdeea..bca20da57a 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -1197,3 +1197,53 @@ Generated by [AVA](https://avajs.dev). 2 |␊ 3 | }␊ ` + +## invalid(42): self.innerWidth + +> Input + + `␊ + 1 | self.innerWidth␊ + ` + +> Output + + `␊ + 1 | globalThis.innerWidth␊ + ` + +> Error 1/1 + + `␊ + > 1 | self.innerWidth␊ + | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ + 1 | globalThis.innerWidth␊ + ` + +## invalid(43): self.innerHeight + +> Input + + `␊ + 1 | self.innerHeight␊ + ` + +> Output + + `␊ + 1 | globalThis.innerHeight␊ + ` + +> Error 1/1 + + `␊ + > 1 | self.innerHeight␊ + | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ + 1 | globalThis.innerHeight␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 7920b68790e8e54e13e27a2090cb3da992a439d3..36239376bdff721cdee7a9abbbb829a89297a4e1 100644 GIT binary patch literal 2555 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 Rh6)jJ`wrBbTqvbj002);1h4=A literal 2473 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 nCUss@A4Z)(Vwhm Date: Mon, 29 Jul 2024 09:31:38 +0800 Subject: [PATCH 13/70] test: update test case --- rules/prefer-global-this.js | 4 +--- test/prefer-global-this.mjs | 10 +++++----- test/snapshots/prefer-global-this.mjs.md | 8 ++++---- test/snapshots/prefer-global-this.mjs.snap | Bin 2555 -> 2556 bytes 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index eba905d811..856ba67fef 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -462,9 +462,7 @@ const create = context => ({ /** @param {import('estree').TryStatement} node */ TryStatement(_node) {}, /** @param {import('estree').CatchClause} node */ - CatchClause(node) { - handleNodes(context, node.param); - }, + CatchClause(_node) {}, // ===== Declarations ===== diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 15a37c36a4..177020c899 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -35,6 +35,11 @@ test.snapshot({ 'import window, {foo} from "xxx"', 'export { window } from "xxx"', 'export * as window from "xxx";', + outdent` + try { + + } catch (window) {} + `, // Use window specify apis 'window.name = "foo"', @@ -139,11 +144,6 @@ test.snapshot({ 'do {} while (window) {}', 'if (window) {}', 'throw window', - // Outdent` - // try { - - // } catch (window) {} - // `, 'var foo = window', outdent` function foo (name = window) { diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index bca20da57a..1f9d94f30d 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -1140,7 +1140,7 @@ Generated by [AVA](https://avajs.dev). 1 | throw globalThis␊ ` -## invalid(40): var foo = window +## invalid(41): var foo = window > Input @@ -1165,7 +1165,7 @@ Generated by [AVA](https://avajs.dev). 1 | var foo = globalThis␊ ` -## invalid(41): function foo (name = window) { } +## invalid(42): function foo (name = window) { } > Input @@ -1198,7 +1198,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(42): self.innerWidth +## invalid(43): self.innerWidth > Input @@ -1223,7 +1223,7 @@ Generated by [AVA](https://avajs.dev). 1 | globalThis.innerWidth␊ ` -## invalid(43): self.innerHeight +## invalid(44): self.innerHeight > Input diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 36239376bdff721cdee7a9abbbb829a89297a4e1..86402882d073a59a7e0343542a4af909f90baae0 100644 GIT binary patch delta 1838 zcmV+}2hsTZ6Z{i0K~_N^Q*L2!b7*gLAa*kf0|2Q zTY#264r1ZpI8l)@BLeFmkymH|R*}Fb0fUj~QUluQT9Z8i9s#|RTmdQpjgyA~AAh0A zC{+8NCz6m?HnNb>m_;^^3Q2Kxn8?2nkqlz>7U$aiXw8uDW|Lyr4U&?!C2MM&H+}SR&R*B zF2^} zB9%bt=Zq5REO?#YS1njk&W7@PRBR<9RYG=0Vs;5L;(rmVPbsTdRDMp(>#V3Oh{){} z<3@TB{f%Ll1Uw1r_OMij9oTkkw@3B7E0TN$5m^iq5d41>0qWzj^8Shd4Y&onGSU~2 z-Bgq>{O!qLk`PN~C#Wjkbqf=AP-v+O(WN zqo?N)_vJ84xigk3?^GwM7m@STG|o+x^&C>xnSwq>TmA*6M_zlYt*EglnZ_2m8zUgQ zh!%7#Ulf0oe8~_kWqO%Iw#Ov*2ZFuPk|T*eC7T4XAUcMmK}4>nHzes8ik9XKC$?PT zN`_Yo2N1+BDMU&5{NGP$>!L%s#87rDAJk_{I+VO+T9gx8{SNR-;Q@s5TZ|Hg$CGg0 zfhww_+YX-Pwu3P4_rebNcCg_OGj9i}A2$CZf7ySxgDStKi}nhVMK!)1WbWIFw2@Tu zyE0g4!b&F9!x6hb8RA|pkb zV_k1J3dlVqtiTS@0pBm1BXbG+L&x&x!hg3Uv%>AL*f$WTZkQg56YA_xJY1-u)^AAfk#uJ8?4pu#a^)`a_=X9`Cx@jv?i4dlwI1Ris z14}s#hP)c58*~NguobAz?>k5KjSYL)wJ(3#qhP!Nb?pGQ=3sjnwqONH+oUT!KL^`T zfd#q}m6yj~!*lJb>#di_<>h7BX7x{KMc9h(fa1YvIam&~4!TrmO~j0JYt@@5vs?Ex zvxrKH>|zVoT{OJ@B5atG6Korm4vnmAH)F})a6gT||07~?TX=#E%IIm)wF|cEdN4w} z)2#2pCC_(zYvRB{s*_eT4%=5q_2kEM3VysB>{tzDF!0}x|2-?v=4c9fTQv;xh2q@nw&=-o0AX+CV$OS z-JmBv=a<2Ob5NUK=2oUkC8nf5hTLC5+|Tog8hTCE)@2mqH+&4?@lGxd{y%lBnBsni z6n7pe&ipH7czIx->rPi{6QoRuby{f$Rr=MvR$BF$8Um`Cml~5??S^A`SI}R--|^ zb&K2hWr2a?+T0Q$lU@}`0)ObiWz15y;i)4Jv)Dt5P0oWzE;DqKBS|Gwb9z5+W(2KMY-Rq6DX~lDsd{-k78P>-T(PnknsbW=>4ygc-$SF%SDT(&@HXb> z789#%KaqeULhfJbQItaS6A8^)c=A7KYN>e1D<8Kr|A~aiGU+uQ#T!{d==gM*Pk@@b cXkOrH){}J!H3DjcldB0x2pIi^f~8mh0A;mx#{d8T delta 1837 zcmV+|2h#Zb6Z;b~K~_N^Q*L2!b7*gLAa*kf0|1{zFzb=@6=!%$q3}P>7oM56Ix58% zC;tUKti+J=NUf1FBLe=hkymH|UXj2j0f&+3QUm(wdXqf?9s#41TmdQp&69@#AAez< zQK-QAj1jb;)$#=w{H-)kHuX?XgeJvOeltKlr^HcP(e*Q7b=M*&V_1P`nhnL zNF`AEIio~63ts2v!VPR69vY1V4X8fX2A2yuTtq6K=t-jPwQM zw`J&;`@+~aQo@zOIV6Qs1*QA8Jnd`}p(*VrsbsFGD5VCI5^0`TqwQgrxo3K^HZ3R6 z=;?XHeL2ih?u@0%JJpHmMdW-njdN3FJ%^Narl60}mVbfik=Nd8D{AaXrm;ot#t6tR zq6Hnx7X^PMUou2XnO^3Q?J>#yfnaa6js?5RvQY4M{qNqNO>*i7l77 zlHrxY0R-_&3Q-b1|Myecy68|YF_az42ld&K4kd4y7UjfNzXQBdcmSdN7NbPr@g$sg zpo;3~wu5K6?I4W%y|4qm9c=i+%-ccght2=UU-p0Ppvtf5qP>D-QH^g0nftaPZ6uX^ zFW8w&s=0A*koMTn-V6(7eptiXnBTY)t0+yyVa-WZiggQGE4;QNJP&{f8 zV4i>c9S1K0EU2cCU6h2Em;`Q8;Y7IqlO=-&$%1;`c?*f~c0rm`TUi*Q&O@2zoV4ZK zPpZyFEUk3dAZez8rBZQQnMyW@`G=(%;|W7c2dfdmdKm3$@LapqWsTPq`|ASj_GB4B7iBs1{|I@DF!0}hLcSOv=16Pz)|^_+!E+cP0k~a^OFzQ{3;6 z;?5(*nSZ4WFAwZ<-RVkgf|Mz-K`ZT`O24|-N~=CoLqJs%Q=zlob%V|Yr`cRkr*pxi zE$amKHSqdexzn#C8c$)1DeX#vJ%8e_EqaZO>t&?2Iixmys(ZfoqIvB*MWrjKrk&Gl z==7t|P79HqOVUn)Zj6;ESu|CeL9M|9vx%Ddq3Xp%E9?QTCTa1GHl3h5pmSOob|m_c zKfongnm@orZBgb5_6HIBf3x3g5W~Y1JjbuCjOGFC<~#>8@HcES*1Oh-wtqER(D7~S zs`OAyzITi{qo)zPPkJD6XyQ9OcaZAfB8u^xL5!#Z32|b2c^T>D*9AqWw)E@l;rWVq za{EzLd#bajzD1_K1-<&JKMd|De+aL#23t!NJIUg)o4&} z-QqTWSzzF}Hn&8`q*q0f0DpRL8MD-FcpAvVEcTFMlk*^w%M9J*NK(nvoZgR{8G|B; zjAt2R(yZ=zu(K-^Ndo#5!t^9)EPurmTbaLNO6-z(s$SlXMTML{SF9|C=G>x5`r*OA_e1FO)u!hbyp8#} z#l$MxPb8p-ko#A96s6GoM8bS6Jo%qAwN$+1m5 Date: Mon, 29 Jul 2024 09:41:39 +0800 Subject: [PATCH 14/70] docs: update README of rule --- docs/rules/prefer-global-this.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index 52f6c52fe0..52cae91d25 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -7,6 +7,10 @@ +This rule will enforce the use of globalThis over window, self, and global. + +But some platform-specific APIs still be allowed (eg `window.innerWidth`, `window.innerHeight`, `window.navigator`). You can find the list of APIs in the source code of this rule. + ## Fail ```js @@ -25,6 +29,17 @@ const { foo } = global ## Pass ```js +// Window specific APIs +window.innerWidth +window.innerHeight +window.addEventListener('click', () => {}) +window.location +window.navigator + +// Worker specific APIs +self.postMessage('Hello') +self.onmessage = () => {} + globalThis globalThis.foo globalThis[foo] From 83419f121385d107b121dd3446b4c7df4e91a6bf Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 29 Jul 2024 09:42:56 +0800 Subject: [PATCH 15/70] test: update test case --- test/snapshots/prefer-global-this.mjs.md | 8 ++++---- test/snapshots/prefer-global-this.mjs.snap | Bin 2556 -> 2555 bytes 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 1f9d94f30d..bca20da57a 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -1140,7 +1140,7 @@ Generated by [AVA](https://avajs.dev). 1 | throw globalThis␊ ` -## invalid(41): var foo = window +## invalid(40): var foo = window > Input @@ -1165,7 +1165,7 @@ Generated by [AVA](https://avajs.dev). 1 | var foo = globalThis␊ ` -## invalid(42): function foo (name = window) { } +## invalid(41): function foo (name = window) { } > Input @@ -1198,7 +1198,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(43): self.innerWidth +## invalid(42): self.innerWidth > Input @@ -1223,7 +1223,7 @@ Generated by [AVA](https://avajs.dev). 1 | globalThis.innerWidth␊ ` -## invalid(44): self.innerHeight +## invalid(43): self.innerHeight > Input diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 86402882d073a59a7e0343542a4af909f90baae0..36239376bdff721cdee7a9abbbb829a89297a4e1 100644 GIT binary patch delta 1837 zcmV+|2h#Zb6Z;b~K~_N^Q*L2!b7*gLAa*kf0|1{zFzb=@6=!%$q3}P>7oM56Ix58% zC;tUKti+J=NUf1FBLe=hkymH|UXj2j0f&+3QUm(wdXqf?9s#41TmdQp&69@#AAez< zQK-QAj1jb;)$#=w{H-)kHuX?XgeJvOeltKlr^HcP(e*Q7b=M*&V_1P`nhnL zNF`AEIio~63ts2v!VPR69vY1V4X8fX2A2yuTtq6K=t-jPwQM zw`J&;`@+~aQo@zOIV6Qs1*QA8Jnd`}p(*VrsbsFGD5VCI5^0`TqwQgrxo3K^HZ3R6 z=;?XHeL2ih?u@0%JJpHmMdW-njdN3FJ%^Narl60}mVbfik=Nd8D{AaXrm;ot#t6tR zq6Hnx7X^PMUou2XnO^3Q?J>#yfnaa6js?5RvQY4M{qNqNO>*i7l77 zlHrxY0R-_&3Q-b1|Myecy68|YF_az42ld&K4kd4y7UjfNzXQBdcmSdN7NbPr@g$sg zpo;3~wu5K6?I4W%y|4qm9c=i+%-ccght2=UU-p0Ppvtf5qP>D-QH^g0nftaPZ6uX^ zFW8w&s=0A*koMTn-V6(7eptiXnBTY)t0+yyVa-WZiggQGE4;QNJP&{f8 zV4i>c9S1K0EU2cCU6h2Em;`Q8;Y7IqlO=-&$%1;`c?*f~c0rm`TUi*Q&O@2zoV4ZK zPpZyFEUk3dAZez8rBZQQnMyW@`G=(%;|W7c2dfdmdKm3$@LapqWsTPq`|ASj_GB4B7iBs1{|I@DF!0}hLcSOv=16Pz)|^_+!E+cP0k~a^OFzQ{3;6 z;?5(*nSZ4WFAwZ<-RVkgf|Mz-K`ZT`O24|-N~=CoLqJs%Q=zlob%V|Yr`cRkr*pxi zE$amKHSqdexzn#C8c$)1DeX#vJ%8e_EqaZO>t&?2Iixmys(ZfoqIvB*MWrjKrk&Gl z==7t|P79HqOVUn)Zj6;ESu|CeL9M|9vx%Ddq3Xp%E9?QTCTa1GHl3h5pmSOob|m_c zKfongnm@orZBgb5_6HIBf3x3g5W~Y1JjbuCjOGFC<~#>8@HcES*1Oh-wtqER(D7~S zs`OAyzITi{qo)zPPkJD6XyQ9OcaZAfB8u^xL5!#Z32|b2c^T>D*9AqWw)E@l;rWVq za{EzLd#bajzD1_K1-<&JKMd|De+aL#23t!NJIUg)o4&} z-QqTWSzzF}Hn&8`q*q0f0DpRL8MD-FcpAvVEcTFMlk*^w%M9J*NK(nvoZgR{8G|B; zjAt2R(yZ=zu(K-^Ndo#5!t^9)EPurmTbaLNO6-z(s$SlXMTML{SF9|C=G>x5`r*OA_e1FO)u!hbyp8#} z#l$MxPb8p-ko#A96s6GoM8bS6Jo%qAwN$+1m5 zTY#264r1ZpI8l)@BLeFmkymH|R*}Fb0fUj~QUluQT9Z8i9s#|RTmdQpjgyA~AAh0A zC{+8NCz6m?HnNb>m_;^^3Q2Kxn8?2nkqlz>7U$aiXw8uDW|Lyr4U&?!C2MM&H+}SR&R*B zF2^} zB9%bt=Zq5REO?#YS1njk&W7@PRBR<9RYG=0Vs;5L;(rmVPbsTdRDMp(>#V3Oh{){} z<3@TB{f%Ll1Uw1r_OMij9oTkkw@3B7E0TN$5m^iq5d41>0qWzj^8Shd4Y&onGSU~2 z-Bgq>{O!qLk`PN~C#Wjkbqf=AP-v+O(WN zqo?N)_vJ84xigk3?^GwM7m@STG|o+x^&C>xnSwq>TmA*6M_zlYt*EglnZ_2m8zUgQ zh!%7#Ulf0oe8~_kWqO%Iw#Ov*2ZFuPk|T*eC7T4XAUcMmK}4>nHzes8ik9XKC$?PT zN`_Yo2N1+BDMU&5{NGP$>!L%s#87rDAJk_{I+VO+T9gx8{SNR-;Q@s5TZ|Hg$CGg0 zfhww_+YX-Pwu3P4_rebNcCg_OGj9i}A2$CZf7ySxgDStKi}nhVMK!)1WbWIFw2@Tu zyE0g4!b&F9!x6hb8RA|pkb zV_k1J3dlVqtiTS@0pBm1BXbG+L&x&x!hg3Uv%>AL*f$WTZkQg56YA_xJY1-u)^AAfk#uJ8?4pu#a^)`a_=X9`Cx@jv?i4dlwI1Ris z14}s#hP)c58*~NguobAz?>k5KjSYL)wJ(3#qhP!Nb?pGQ=3sjnwqONH+oUT!KL^`T zfd#q}m6yj~!*lJb>#di_<>h7BX7x{KMc9h(fa1YvIam&~4!TrmO~j0JYt@@5vs?Ex zvxrKH>|zVoT{OJ@B5atG6Korm4vnmAH)F})a6gT||07~?TX=#E%IIm)wF|cEdN4w} z)2#2pCC_(zYvRB{s*_eT4%=5q_2kEM3VysB>{tzDF!0}x|2-?v=4c9fTQv;xh2q@nw&=-o0AX+CV$OS z-JmBv=a<2Ob5NUK=2oUkC8nf5hTLC5+|Tog8hTCE)@2mqH+&4?@lGxd{y%lBnBsni z6n7pe&ipH7czIx->rPi{6QoRuby{f$Rr=MvR$BF$8Um`Cml~5??S^A`SI}R--|^ zb&K2hWr2a?+T0Q$lU@}`0)ObiWz15y;i)4Jv)Dt5P0oWzE;DqKBS|Gwb9z5+W(2KMY-Rq6DX~lDsd{-k78P>-T(PnknsbW=>4ygc-$SF%SDT(&@HXb> z789#%KaqeULhfJbQItaS6A8^)c=A7KYN>e1D<8Kr|A~aiGU+uQ#T!{d==gM*Pk@@b cXkOrH){}J!H3DjcldB0x2pIi^f~8mh0A;mx#{d8T From b6e28902d8714fc4416ad1f351607705eee3bbc0 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 29 Jul 2024 09:51:48 +0800 Subject: [PATCH 16/70] test: add more test case --- test/prefer-global-this.mjs | 1 + test/snapshots/prefer-global-this.mjs.md | 25 +++++++++++++++++++++ test/snapshots/prefer-global-this.mjs.snap | Bin 2555 -> 2598 bytes 3 files changed, 26 insertions(+) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 177020c899..35643442e6 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -152,6 +152,7 @@ test.snapshot({ `, 'self.innerWidth', 'self.innerHeight', + 'window.crypto', ], }); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index bca20da57a..bd29794cc9 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -1247,3 +1247,28 @@ Generated by [AVA](https://avajs.dev). Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ 1 | globalThis.innerHeight␊ ` + +## invalid(44): window.crypto + +> Input + + `␊ + 1 | window.crypto␊ + ` + +> Output + + `␊ + 1 | globalThis.crypto␊ + ` + +> Error 1/1 + + `␊ + > 1 | window.crypto␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.crypto␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 36239376bdff721cdee7a9abbbb829a89297a4e1..03ab865e9fa32ca240d60ac85b3da3bc2a89750c 100644 GIT binary patch literal 2598 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 Rh6)jJ`wrBbTqvbj002);1h4=A From 287ee97051f6e439db8167573156d5dd5397543a Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 29 Jul 2024 10:48:13 +0800 Subject: [PATCH 17/70] docs: update readme --- docs/rules/prefer-global-this.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index 52cae91d25..a768a43fb2 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -7,9 +7,9 @@ -This rule will enforce the use of globalThis over window, self, and global. +This rule will enforce the use of `globalThis` over `window`, `self`, and `global`. -But some platform-specific APIs still be allowed (eg `window.innerWidth`, `window.innerHeight`, `window.navigator`). You can find the list of APIs in the source code of this rule. +But some platform-specific APIs still be allowed (e.g. `window.innerWidth`, `window.innerHeight`, `window.navigator`). You can find the list of APIs in the source code of this rule. ## Fail From c2289b1ffb6b37241662089add7a36772bf610b2 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 29 Jul 2024 11:29:03 +0800 Subject: [PATCH 18/70] update apis update --- rules/prefer-global-this.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 856ba67fef..526398cd38 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -209,12 +209,9 @@ const windowSpecificAPIs = new Set([ 'XPathEvaluator', 'XSLTProcessor', - // Refs: https://www.w3.org/TR/window-management/#usage-overview - 'screen', - 'getScreenDetails', - - // Refs: https://drafts.csswg.org/cssom-view/#extensions-to-the-window-interface + // Refs: https://drafts.csswg.org/cssom-view/#idl-index 'matchMedia', + 'screen', 'visualViewport', 'moveTo', 'moveBy', @@ -236,6 +233,11 @@ const windowSpecificAPIs = new Set([ 'screenWidth', 'screenHeight', 'devicePixelRatio', + 'MediaQueryList', + 'MediaQueryListEvent', + 'Screen', + 'CaretPosition', + 'VisualViewport', ]); const webWorkerSpecificAPIs = new Set([ From 1368a756e630dc7c95ac4d478eac3c3e770875cf Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 29 Jul 2024 12:48:37 +0200 Subject: [PATCH 19/70] Update prefer-global-this.js --- rules/prefer-global-this.js | 39 +++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 526398cd38..58578ba82c 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -8,11 +8,11 @@ const messages = { }; /** - * Find the variable in the scope - * @param {import('eslint').Scope.Scope} scope - * @param {string} variableName - * @returns - */ +Find the variable in the scope. + +@param {import('eslint').Scope.Scope} scope +@param {string} variableName +*/ function findVariableInScope(scope, variableName) { if (!scope || scope.type === 'global') { return; @@ -30,8 +30,8 @@ function findVariableInScope(scope, variableName) { const globalIdentifier = new Set(['window', 'self', 'global']); const windowSpecificAPIs = new Set([ - // Refs: https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-window-object // Properties and methods + // https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-window-object 'window', 'self', 'document', @@ -166,12 +166,12 @@ const windowSpecificAPIs = new Set([ 'onunhandledrejection', 'onunload', - // Refs: https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow + // https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow 'addEventListener', 'removeEventListener', 'dispatchEvent', - // Refs: https://dom.spec.whatwg.org/#idl-index + // https://dom.spec.whatwg.org/#idl-index 'Event', 'event', 'CustomEvent', @@ -209,7 +209,7 @@ const windowSpecificAPIs = new Set([ 'XPathEvaluator', 'XSLTProcessor', - // Refs: https://drafts.csswg.org/cssom-view/#idl-index + // https://drafts.csswg.org/cssom-view/#idl-index 'matchMedia', 'screen', 'visualViewport', @@ -241,7 +241,7 @@ const windowSpecificAPIs = new Set([ ]); const webWorkerSpecificAPIs = new Set([ - // Refs: https://html.spec.whatwg.org/multipage/workers.html#the-workerglobalscope-common-interface + // https://html.spec.whatwg.org/multipage/workers.html#the-workerglobalscope-common-interface 'addEventListener', 'removeEventListener', 'dispatchEvent', @@ -256,18 +256,17 @@ const webWorkerSpecificAPIs = new Set([ 'onrejectionhandled', 'onunhandledrejection', - // Refs: https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-dedicatedworkerglobalscope-interface + // https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-dedicatedworkerglobalscope-interface 'name', 'postMessage', 'onconnect', ]); /** - * - * @param {import('eslint').Rule.RuleContext} context - * @param {import('estree').Node} node - * @param {string} value - */ +@param {import('eslint').Rule.RuleContext} context +@param {import('estree').Node} node +@param {string} value +*/ function report(context, node, value) { context.report({ node, @@ -291,11 +290,9 @@ function report(context, node, value) { } /** - * - * @param {import('eslint').Rule.RuleContext} context - * @param {import('estree').Node | Array} nodes - * @returns - */ +@param {import('eslint').Rule.RuleContext} context +@param {import('estree').Node | Array} nodes +*/ function handleNodes(context, nodes) { if (!Array.isArray(nodes)) { nodes = [nodes]; From 9689caedcb2da88dd3a182bed966e83248589354 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 29 Jul 2024 12:50:19 +0200 Subject: [PATCH 20/70] Update prefer-global-this.md --- docs/rules/prefer-global-this.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index a768a43fb2..94e57b83c0 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -9,7 +9,7 @@ This rule will enforce the use of `globalThis` over `window`, `self`, and `global`. -But some platform-specific APIs still be allowed (e.g. `window.innerWidth`, `window.innerHeight`, `window.navigator`). You can find the list of APIs in the source code of this rule. +However, some window-specific APIs are still allowed (e.g. `window.innerWidth`, `window.innerHeight`, `window.navigator`). You can find the list of APIs in the source code of this rule. ## Fail @@ -22,8 +22,8 @@ global global.foo global[foo] global.foo() -const { foo } = window -const { foo } = global +const {foo} = window +const {foo} = global ``` ## Pass @@ -44,5 +44,5 @@ globalThis globalThis.foo globalThis[foo] globalThis.foo() -const { foo } = globalThis +const {foo} = globalThis ``` From c8e4217f2eaf6e171c0251d3829b43d236750fb5 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 29 Jul 2024 12:51:02 +0200 Subject: [PATCH 21/70] Update prefer-global-this.js --- rules/prefer-global-this.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 58578ba82c..94682ebbb2 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -18,7 +18,7 @@ function findVariableInScope(scope, variableName) { return; } - const variable = scope.variables.find(v => v.name === variableName); + const variable = scope.variables.find(variable => variable.name === variableName); if (variable) { return variable; From 1543ced8169f5bfc6caf8b0db876444c2ab6fde2 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 30 Jul 2024 01:05:22 +0700 Subject: [PATCH 22/70] Filter out some properties --- rules/prefer-global-this.js | 144 ++---------------------------------- 1 file changed, 5 insertions(+), 139 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 94682ebbb2..bc53ddbb97 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -32,14 +32,7 @@ const globalIdentifier = new Set(['window', 'self', 'global']); const windowSpecificAPIs = new Set([ // Properties and methods // https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-window-object - 'window', - 'self', - 'document', 'name', - 'location', - 'history', - 'navigation', - 'customElements', 'locationbar', 'menubar', 'personalbar', @@ -59,158 +52,36 @@ const windowSpecificAPIs = new Set([ 'parent', 'frameElement', 'open', - 'object', - 'navigator', - 'clientInformation', 'originAgentCluster', - 'alert', - 'confirm', - 'prompt', - 'print', 'postMessage', - // global events - 'onabort', - 'onauxclick', - 'onbeforeinput', - 'onbeforematch', - 'onbeforetoggle', + // Events commonly associated with "window" + 'onresize', 'onblur', - 'oncancel', - 'oncanplay', - 'oncanplaythrough', - 'onchange', - 'onclick', - 'onclose', - 'oncontextlost', - 'oncontextmenu', - 'oncontextrestored', - 'oncopy', - 'oncuechange', - 'oncut', - 'ondblclick', - 'ondrag', - 'ondragend', - 'ondragenter', - 'ondragleave', - 'ondragover', - 'ondragstart', - 'ondrop', - 'ondurationchange', - 'onemptied', - 'onended', - 'onerror', 'onfocus', - 'onformdata', - 'oninput', - 'oninvalid', - 'onkeydown', - 'onkeypress', - 'onkeyup', 'onload', - 'onloadeddata', - 'onloadedmetadata', - 'onloadstart', - 'onmousedown', - 'onmouseenter', - 'onmouseleave', - 'onmousemove', - 'onmouseout', - 'onmouseover', - 'onmouseup', - 'onpaste', - 'onpause', - 'onplay', - 'onplaying', - 'onprogress', - 'onratechange', - 'onreset', - 'onresize', 'onscroll', 'onscrollend', - 'onsecuritypolicyviolation', - 'onseeked', - 'onseeking', - 'onselect', - 'onslotchange', - 'onstalled', - 'onsubmit', - 'onsuspend', - 'ontimeupdate', - 'ontoggle', - 'onvolumechange', - 'onwaiting', - 'onwebkitanimationend', - 'onwebkitanimationiteration', - 'onwebkitanimationstart', - 'onwebkittransitionend', 'onwheel', - - // Window events - 'onafterprint', - 'onbeforeprint', - 'onbeforeunload', - 'onhashchange', - 'onlanguagechange', + 'onbeforeunload', // Browsers might have specific behaviors on exactly `window.onbeforeunload =` 'onmessage', 'onmessageerror', - 'onoffline', - 'ononline', 'onpagehide', 'onpagereveal', 'onpageshow', 'onpageswap', - 'onpopstate', - 'onrejectionhandled', - 'onstorage', - 'onunhandledrejection', 'onunload', + // To add/remove/dispatch events that are commonly associated with "window" // https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow 'addEventListener', 'removeEventListener', 'dispatchEvent', // https://dom.spec.whatwg.org/#idl-index - 'Event', - 'event', - 'CustomEvent', - 'EventTarget', - 'AbortController', - 'AbortSignal', - 'NodeList', - 'HTMLCollection', - 'MutationObserver', - 'MutationRecord', - 'EventTarget', - 'Document', - 'XMLDocument', - 'DOMImplementation', - 'DocumentType', - 'DocumentFragment', - 'ShadowRoot', - 'Element', - 'NamedNodeMap', - 'Attr', - 'CharacterData', - 'Text', - 'CDATASection', - 'ProcessingInstruction', - 'Comment', - 'AbstractRange', - 'StaticRange', - 'Range', - 'NodeIterator', - 'TreeWalker', - 'NodeFilter', - 'DOMTokenList', - 'XPathResult', - 'XPathExpression', - 'XPathEvaluator', - 'XSLTProcessor', + 'event', // Deprecated and quirky, best left untouched // https://drafts.csswg.org/cssom-view/#idl-index - 'matchMedia', 'screen', 'visualViewport', 'moveTo', @@ -233,11 +104,6 @@ const windowSpecificAPIs = new Set([ 'screenWidth', 'screenHeight', 'devicePixelRatio', - 'MediaQueryList', - 'MediaQueryListEvent', - 'Screen', - 'CaretPosition', - 'VisualViewport', ]); const webWorkerSpecificAPIs = new Set([ From 588e158e28609e3247122c49fb46c79c9776525a Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 30 Jul 2024 09:25:05 +0800 Subject: [PATCH 23/70] fix: test case --- test/prefer-global-this.mjs | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 35643442e6..76b795d4cc 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -43,8 +43,6 @@ test.snapshot({ // Use window specify apis 'window.name = "foo"', - 'window.alert()', - 'var doc = window.document', 'window.addEventListener', 'window.innerWidth', 'window.innerHeight', From 71fdcd8865fcfa2cef076960c3178c8e20771cdf Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 30 Jul 2024 09:25:33 +0800 Subject: [PATCH 24/70] Update test/prefer-global-this.mjs Co-authored-by: Sindre Sorhus --- test/prefer-global-this.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 76b795d4cc..7b67547b5c 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -41,7 +41,7 @@ test.snapshot({ } catch (window) {} `, - // Use window specify apis + // Use window specific APIs 'window.name = "foo"', 'window.addEventListener', 'window.innerWidth', From 27d70961c4571fdd4f723bfaec9b7d89e28fce59 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 30 Jul 2024 09:25:55 +0800 Subject: [PATCH 25/70] Update docs/rules/prefer-global-this.md Co-authored-by: Sindre Sorhus --- docs/rules/prefer-global-this.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index 94e57b83c0..040b12f28c 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -1,4 +1,4 @@ -# Prefer `globalThis` instead of `window`, `self` and `global` +# Prefer `globalThis` over `window`, `self`, and `global` 💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs-eslintconfigjs). From b9cc588d3a0203651ed8921a58c8d63ac18304e4 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 30 Jul 2024 09:29:46 +0800 Subject: [PATCH 26/70] fix: eslint-doc-generator --- readme.md | 2 +- rules/prefer-global-this.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 0dee448e13..9013888417 100644 --- a/readme.md +++ b/readme.md @@ -189,7 +189,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c | [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. | ✅ | | 💡 | | [prefer-event-target](docs/rules/prefer-event-target.md) | Prefer `EventTarget` over `EventEmitter`. | ✅ | | | | [prefer-export-from](docs/rules/prefer-export-from.md) | Prefer `export…from` when re-exporting. | ✅ | 🔧 | 💡 | -| [prefer-global-this](docs/rules/prefer-global-this.md) | Prefer `globalThis` instead of `window`, `self` and `global`. | ✅ | 🔧 | 💡 | +| [prefer-global-this](docs/rules/prefer-global-this.md) | Prefer `globalThis` over `window`, `self`, and `global`. | ✅ | 🔧 | 💡 | | [prefer-includes](docs/rules/prefer-includes.md) | Prefer `.includes()` over `.indexOf()`, `.lastIndexOf()`, and `Array#some()` when checking for existence or non-existence. | ✅ | 🔧 | 💡 | | [prefer-json-parse-buffer](docs/rules/prefer-json-parse-buffer.md) | Prefer reading a JSON file as a buffer. | | 🔧 | | | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | ✅ | 🔧 | | diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index bc53ddbb97..bc8c6770e9 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -347,7 +347,7 @@ module.exports = { meta: { type: 'suggestion', docs: { - description: 'Prefer `globalThis` instead of `window`, `self` and `global`.', + description: 'Prefer `globalThis` over `window`, `self`, and `global`.', recommended: true, }, fixable: 'code', From fecdfff673843818a506b2aa2235844586dd1c72 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 30 Jul 2024 09:35:57 +0800 Subject: [PATCH 27/70] docs: update docs --- docs/rules/prefer-global-this.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index 040b12f28c..88b0cd2111 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -9,7 +9,7 @@ This rule will enforce the use of `globalThis` over `window`, `self`, and `global`. -However, some window-specific APIs are still allowed (e.g. `window.innerWidth`, `window.innerHeight`, `window.navigator`). You can find the list of APIs in the source code of this rule. +However, some window-specific APIs are still allowed (e.g. `window.innerWidth`, `window.innerHeight`, `window.navigator`). You can find the list of APIs in the [source code](../../rules/prefer-global-this.js) of this rule. ## Fail From b258aa1102ef6c14a1a758a8c3c30f96688511f2 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 30 Jul 2024 09:58:57 +0800 Subject: [PATCH 28/70] feat: report error in some event that dost not relative to window --- rules/prefer-global-this.js | 47 ++++++++++++------- test/prefer-global-this.mjs | 4 ++ test/snapshots/prefer-global-this.mjs.md | 50 +++++++++++++++++++++ test/snapshots/prefer-global-this.mjs.snap | Bin 2598 -> 2720 bytes 4 files changed, 85 insertions(+), 16 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index bc8c6770e9..013c676f2d 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -29,6 +29,24 @@ function findVariableInScope(scope, variableName) { const globalIdentifier = new Set(['window', 'self', 'global']); +const windowSpecificEvents = new Set([ + 'resize', + 'blur', + 'focus', + 'load', + 'scroll', + 'scrollend', + 'wheel', + 'beforeunload', // Browsers might have specific behaviors on exactly `window.onbeforeunload =` + 'message', + 'messageerror', + 'pagehide', + 'pagereveal', + 'pageshow', + 'pageswap', + 'unload', +]); + const windowSpecificAPIs = new Set([ // Properties and methods // https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-window-object @@ -56,21 +74,7 @@ const windowSpecificAPIs = new Set([ 'postMessage', // Events commonly associated with "window" - 'onresize', - 'onblur', - 'onfocus', - 'onload', - 'onscroll', - 'onscrollend', - 'onwheel', - 'onbeforeunload', // Browsers might have specific behaviors on exactly `window.onbeforeunload =` - 'onmessage', - 'onmessageerror', - 'onpagehide', - 'onpagereveal', - 'onpageshow', - 'onpageswap', - 'onunload', + ...[...windowSpecificEvents].map(event => `on${event}`), // To add/remove/dispatch events that are commonly associated with "window" // https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow @@ -190,7 +194,18 @@ const create = context => ({ if (node.object.type === 'Identifier') { // Check if the identifier is a window specific API if (node.object.name === 'window' && node.property.type === 'Identifier' && windowSpecificAPIs.has(node.property.name)) { - return; + // Allow to use window.addEventListener/removeEventListener/dispatchEvent with windowSpecificEvents + if (['addEventListener', 'removeEventListener', 'dispatchEvent'].includes(node.property.name)) { + if (node.parent && node.parent.type === 'CallExpression') { + if (node.parent.arguments.length > 0 && node.parent.arguments[0].type === 'Literal' && windowSpecificEvents.has(node.parent.arguments[0].value)) { + return; + } + } else { + return; + } + } else { + return; + } } // Check if the identifier is a web worker specific API diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 7b67547b5c..fd2a8c1345 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -48,6 +48,8 @@ test.snapshot({ 'window.innerHeight', 'self.location', 'self.navigator', + 'window.addEventListener("resize", () => {})', + 'window.onresize = function () {}', ], invalid: [ 'global', @@ -151,6 +153,8 @@ test.snapshot({ 'self.innerWidth', 'self.innerHeight', 'window.crypto', + 'window.addEventListener("play", () => {})', + 'window.onplay = function () {}', ], }); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index bd29794cc9..5fd0892851 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -1272,3 +1272,53 @@ Generated by [AVA](https://avajs.dev). Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ 1 | globalThis.crypto␊ ` + +## invalid(45): window.addEventListener("play", () => {}) + +> Input + + `␊ + 1 | window.addEventListener("play", () => {})␊ + ` + +> Output + + `␊ + 1 | globalThis.addEventListener("play", () => {})␊ + ` + +> Error 1/1 + + `␊ + > 1 | window.addEventListener("play", () => {})␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.addEventListener("play", () => {})␊ + ` + +## invalid(46): window.onplay = function () {} + +> Input + + `␊ + 1 | window.onplay = function () {}␊ + ` + +> Output + + `␊ + 1 | globalThis.onplay = function () {}␊ + ` + +> Error 1/1 + + `␊ + > 1 | window.onplay = function () {}␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ + 1 | globalThis.onplay = function () {}␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 03ab865e9fa32ca240d60ac85b3da3bc2a89750c..35533dfdc607f9c991146316414efce6415c96eb 100644 GIT binary patch literal 2720 zcmV;R3Sad>RzVC6eI$D z#y^j1gdd9t00000000B!oZFAwRvpK8mR67v0!j zKAsI_?aouQ@$cf_=X)+b=h(j*^<97P+T@q@x9rdfT|02RJ=Eh6wXB`}Q<*I!e8a^)vm`)S0JRG#U-UG2iY;|=|NQ~l4b{$J}qiejk$ z+0~ycgDB=nDC|)R9Y&!(@_mtnyt1){jK&hO`KpiS3vPm?cK^Awu+?*nTS2f-piwP`9CLj1lyp*~r$0rY7^W zA>J@U8=9FFgAZQNY~HJZ070bkY$E`F0v~~JK~EVLVAQfOg3gsX>(KAmgJOp8*@rCtCZIC z4@BvYTx*IWa?L5HtQ4gXSv|&BHPOrgHlW#Ri@fBOPuj_tT}GDYq=P52#@zmixcy0- zMMSp6XkkJzbgirv_k{{-+P+XpEVVCG)6(~aMIx0#=}|_BtStEbAJ#3{Q1*uMXH;w@ zBUM3mXA^cQJ>q{5tG`fIiKu*^nAcuWSrC!i6~>LMMT~a60SR~+wr#Icg(En0YDJk9e&r6;U1bd?) zM-sgtlLWCKI)-F{h+Iz}NU|{$EzKFuY`Mgh4DXZ{5yX!vL`nGkKTm1vqC>gHQ1-0= z)O$-hl)PnDlrvlX4De3ra|q?XFiI32cfxrGs;G``I(VI%4#IT37mgsX!`;A}dpbz{ zu>K$Un}0f}@@qP1Zy;IJlhZ-wzNbhVNhRL{_S_}aJh->W@|b7uM+GzAtl@3UAKZym zoTg&4=5Gl3A81d2BF13z+4dEM5J|njNRh>{f$vR1@(c+Za71*#ua_;8zJ&duZw1TI zzq^uN;mxSnZy-*CC_NM>(%G40xJYGZl2OY59rAY^ybQ3S>OziD5`JnDc##Sx!u_8t z8PrHt)cwxSkqF-`NptEc3q#a-X0ARbYdKGos^=q?RXVJZv@^j{sko<1Wj=`chox%c zDNRcUs};lg1%ma{Y_L?i=_yi)5oV-V1YVkkrR)YHUhS)GIs*0C2-M=|ofG?wUE3Sj zx9v$doq)P_2nWk>xDE%f0hL3tD&1IyL#V+D9f_*z)7$V}yYBki6>@oXT{c<$2^tX& zk~5%Wa9R$Q1FeHD6<%JzDau6eMMiuL`ME6d zgXed8?C9j|;sd1!drDeGS@kilnka@g69d`B*|P$egaK^8)>u-ued6naL=I8FCY`~WJXU$w$80Eg}vkOx`G<7f{NXs`_&m5JsuR^&RNpF7--=#+_33`H zT7lWs!THUgLirPnS#=CzC6xFoQsTGFl}JNk)$%$;`C{p%or3&WW2-}lf~+x4@bvBktCq6AWVjB^t?ctYmDWIppC!h9datV%>Ojm_uGCcRLaS4`Vv4cr;&3CmwG#a8C8m=e2m zo~oC(6Hy`O=ZclZ(Ck~Z$$EG=4t#pP+H~K7w=v(hm|4yDi3Ai8a{o$?q7<4>By<|l z&i`ytOT|lG`J|osClX@IwAXkPZ)6Fflig)L0cz@^d4Z?XOuWDY70-IzX2ns=fD{XT zT0iNV1?a8V(wfd|=FO;^NDQlNIVde<-5x z$iM!SFf%{S!94&7=0Y>z|JemrS6&->95d!x6ogxJNv zh6*8aJIlCnp9LKRhdZICz=__h{+FJafu>Rqb7!9LLpAi;xcH~x;pW9 zLhIIWcyrJ8!sneyXnS^0xwzw6hZmQjQiY8k934yEd)!1kniylcLmA?yk;@hF-i+NQ z23j<0TYR*H`5SmGh&GJtr`ek8aNjTWJz@_V@t|FiKhnxiTI;=-pS0%gQ12@ti-(Xb a?oY@<<*FcB&{rxJz<&Xg_6XRCUH||k09Atk literal 2598 zcmV+>3fc8RRzVLNKN#J;6Xr6C&;2C?%wfZ)T2|G?OLOIn{H|{*@`<_qSgcP>9+7Vv_5z;;EVX`r6O6%*&wj`&-+n7_DStYcl zuMnkwbFC?g$Tg>&vQm^nWOW~7)kHG~Sc7J(E%K6AK5i#tb{1Klln$QA8gu&^ar;o5 zMTEA+XkkJzbgirv^@R#*+P+XpEU_0U;OtSorFm+BU*DSJctGb*-{ zk*XlO6EVAl9`XN()hCoyEGpk8=CxN;7DVKBj&UPv5yS0qp9DM$oA$U;g?-p_Y{O!qLf-pN@VfGn(U4H%stbSwPQJfMo*6;?yF&za%U`6-loKIP3nhJwuKWgyBd^2NR@B)2Ok>O3gAtHfLgrZ2;vtMq9lC&pQp5S(V<*nD0`L< z>b)f$O5QRp%9*Wx26(k}3qtu{j1q;%op9cPDypNK4qoJ@gD_q1g?;etVA~&Oo(@t! ztp7*;vQGz9eoY7MH6)9Ad^*V7cNJ+PspNaW&RkN>gL{iCkB#k}uwdq!HN1`agFCT` z(o}5Le2I|%i}nO4VgxpyZC_CckbWd*ew!o*`ik_K6Po^|A%hm#{zdEPo;V zcSq7IycQPwRm7 zG%X#hRs`!W2-cs|!BXj_t4Jk6n37@Td2-IUEP>Y{;PV85=?Q!3} zVo!qU1k|+y*j<3VRoI0!sO*td>Ba)=K@FDZNK{>&-iGJeb=TXhkjty9vdQY7(1@@b zp8>^#({ivJXdQH^(3*%D>Bg$pQD)a~Xl4%$Mv}7a5MQSyqCgvLC7PC* zH<>toh5WVD{^ECwea1v`0g0qSMPityD3)AnCUr4I?VMuTA-gjJ+qDB*d%pdb2RZCE#ctCM~KwlDJd3-0?H>F$?fabQdc-8@i6pAG1dS-LA>Quyav?`I`P?91qU96W@D8bnQFC| zlKvQSe;RSW#3yR#HCbEFqZm){F@)otTpav=>R2(w{T3lM`EoFFl;E3x^S85Za zOo=U8X$MvMg~L`_^(zbkRZUEV&epD5v@bZ%`hq6y3ueo*PGG+R-jFMI`jJHADO_So zJCb0J__jr_v39+R)V6@srcd?I&t5dIBd4fz1=TF)v|Bp;D74c-q!*I3lb{=8B}xWO zm1fY=;Ia8c&HPaHVxkpxfU8ZGcqcnf&>zu0tqS`ReaH`RiI(OExTr14T*3Y(#Qs0* zn+;-kD8M;>ZDlkEu-l6q%)sBaNn7t*6S}O?fu3($FH1MYPm0t5a%o6$sI*i9jeZv`j(mcmh|eYPxq76 z3QVsK&Tk48%Aa7&s$&o7zKAF({JAc%CsPi`4@U_78+2NkE@NnC_>` z`6h~4m55{-o6ng|a-lS@n6}9pxHHrfmcL?(t;}CBC3eX? zRWEPHqC(Ek6)TIO*|%tu_3&Wid-Qy@>AnSTW4>=Ov&!~~1QZc+|4NUd6q-*YEH=WO z|JkCJikH0daXa%*Bt(`;ukk3}$Pz-wyUTn6)YL`u0?%SI_5u%7#?~t~D~@6Yq*&?e#IVekgOXBKE>Ra^X*yeJMLnHldZORztUKee?LX%Xf{`d6 z`PZLfX6DB^xCa2i+-MIv9vO1}T~DzLx_-QkkX^Q&%~4?5kH_t@ydN#GH+l<8h+Pb9 zs1PEz6O0@8S Date: Tue, 30 Jul 2024 13:19:20 +0700 Subject: [PATCH 29/70] Discard changes to .github/workflows/title-formatter.yml --- .github/workflows/title-formatter.yml | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 .github/workflows/title-formatter.yml diff --git a/.github/workflows/title-formatter.yml b/.github/workflows/title-formatter.yml deleted file mode 100644 index f5a1e332c0..0000000000 --- a/.github/workflows/title-formatter.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Title formatter - -on: - pull_request_target: - types: [opened, edited] - issues: - types: [opened, edited] - -jobs: - Rule: - runs-on: ubuntu-latest - permissions: - pull-requests: write - issues: write - steps: - - uses: actions/checkout@v4 - - name: Auto-format rule names in titles - uses: fregante/title-replacer-action@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - pattern-path: docs/rules - replacement: '`$0`' - trim-punctuation: true From 0bc477d347a576cf0169c24701a7ef31c83c3343 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 30 Jul 2024 14:50:10 +0800 Subject: [PATCH 30/70] test: add test for jsdom --- test/prefer-global-this.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index fd2a8c1345..47db742630 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -50,6 +50,10 @@ test.snapshot({ 'self.navigator', 'window.addEventListener("resize", () => {})', 'window.onresize = function () {}', + outdent` + const {window} = jsdom() + window.jQuery = jQuery; + `, ], invalid: [ 'global', From a7bbe9f8cd8bed02a527a1bfb65aab209f7da486 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 30 Jul 2024 14:51:09 +0800 Subject: [PATCH 31/70] docs: update --- docs/rules/prefer-global-this.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index 88b0cd2111..0c91956ecb 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -24,6 +24,10 @@ global[foo] global.foo() const {foo} = window const {foo} = global + +window.addEventListener('click', () => {}) +window.location +window.navigator ``` ## Pass @@ -32,9 +36,6 @@ const {foo} = global // Window specific APIs window.innerWidth window.innerHeight -window.addEventListener('click', () => {}) -window.location -window.navigator // Worker specific APIs self.postMessage('Hello') From 7bb73ec3d9e9459e03c69c6bf35b3348c6b72999 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 30 Jul 2024 14:56:37 +0800 Subject: [PATCH 32/70] docs: Add description of windowSpecificAPIs --- rules/prefer-global-this.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 013c676f2d..726de7922d 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -47,6 +47,14 @@ const windowSpecificEvents = new Set([ 'unload', ]); +/** + * Note: What kind of API should be a windows-specific interfaces? + * it's directly related to window (✅ window.close()) + * it does NOT work well as globalThis.x or x (✅ window.frames, window.top) + * some constructors are occasionally related to window (like Element !== iframe.contentWindow.Element), but they don't need to mention window anyway. + * + * Please use this criterion to decide whether an API should be added here. refs: https://github.com/sindresorhus/eslint-plugin-unicorn/pull/2410#discussion_r1695312427 + */ const windowSpecificAPIs = new Set([ // Properties and methods // https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-window-object From 8be6891e329097fb40a754c33b8a33e303751658 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Wed, 31 Jul 2024 09:59:19 +0800 Subject: [PATCH 33/70] docs: update --- docs/rules/prefer-global-this.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index 0c91956ecb..786d9ff1ec 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -9,7 +9,7 @@ This rule will enforce the use of `globalThis` over `window`, `self`, and `global`. -However, some window-specific APIs are still allowed (e.g. `window.innerWidth`, `window.innerHeight`, `window.navigator`). You can find the list of APIs in the [source code](../../rules/prefer-global-this.js) of this rule. +However, some window-specific APIs are still allowed (e.g. `window.innerWidth`, `window.innerHeight`). You can find the list of APIs in the [source code](../../rules/prefer-global-this.js) of this rule. ## Fail From e15c21306f19abd52bcb64c0155bd938dec92a5d Mon Sep 17 00:00:00 2001 From: Axetroy Date: Wed, 31 Jul 2024 14:13:45 +0800 Subject: [PATCH 34/70] refactor: improve the code --- rules/prefer-global-this.js | 45 ++++++++++--------------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 726de7922d..8c79ae3d75 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -9,23 +9,17 @@ const messages = { /** Find the variable in the scope. - @param {import('eslint').Scope.Scope} scope @param {string} variableName */ -function findVariableInScope(scope, variableName) { +const findVariableInScope = (scope, variableName) => { if (!scope || scope.type === 'global') { return; } const variable = scope.variables.find(variable => variable.name === variableName); - - if (variable) { - return variable; - } - - return findVariableInScope(scope.upper, variableName); -} + return variable || findVariableInScope(scope.upper, variableName); +}; const globalIdentifier = new Set(['window', 'self', 'global']); @@ -141,33 +135,24 @@ const webWorkerSpecificAPIs = new Set([ ]); /** +Report the node with a message. @param {import('eslint').Rule.RuleContext} context @param {import('estree').Node} node @param {string} value */ function report(context, node, value) { + const fix = (/** @type {import('eslint').Rule.RuleFixer} fixer */ fixer) => fixer.replaceText(node, 'globalThis'); context.report({ node, messageId: MESSAGE_ID_ERROR, - data: { - value, - replacement: 'globalThis', - }, - fix: fixer => fixer.replaceText(node, 'globalThis'), - suggest: [ - { - messageId: MESSAGE_ID_SUGGESTION, - data: { - value, - replacement: 'globalThis', - }, - fix: fixer => fixer.replaceText(node, 'globalThis'), - }, - ], + data: {value, replacement: 'globalThis'}, + fix, + suggest: [{messageId: MESSAGE_ID_SUGGESTION, data: {value, replacement: 'globalThis'}, fix}], }); } /** +Handle nodes and check if they should be reported. @param {import('eslint').Rule.RuleContext} context @param {import('estree').Node | Array} nodes */ @@ -178,16 +163,10 @@ function handleNodes(context, nodes) { for (const node of nodes) { if (node && node.type === 'Identifier' && globalIdentifier.has(node.name)) { - const variable = findVariableInScope( - context.sourceCode.getScope(node), - node.name, - ); - - if (variable) { - return; + const variable = findVariableInScope(context.sourceCode.getScope(node), node.name); + if (!variable) { + report(context, node, node.name); } - - report(context, node, node.name); } } } From abaffc245547bf0080778506987f1ba9c3114092 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Wed, 31 Jul 2024 14:22:03 +0800 Subject: [PATCH 35/70] refactor: Simplify the MemberExpression's logic --- rules/prefer-global-this.js | 53 ++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 8c79ae3d75..717602615b 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -171,34 +171,43 @@ function handleNodes(context, nodes) { } } +/** +Check if the node is a window specific API +@param {import('estree').MemberExpression} node +@returns {boolean} +*/ +const isWindowSpecificAPI = node => { + if (node.object.name !== 'window' || node.property.type !== 'Identifier') { + return false; + } + + if (windowSpecificAPIs.has(node.property.name)) { + if (['addEventListener', 'removeEventListener', 'dispatchEvent'].includes(node.property.name) && node.parent && node.parent.type === 'CallExpression') { + const argument = node.parent.arguments[0]; + return argument && argument.type === 'Literal' && windowSpecificEvents.has(argument.value); + } + + return true; + } + + return false; +}; + +/** +Check if the node is a web worker specific API +@param {import('estree').MemberExpression} node +@returns {boolean} +*/ +const isWebWorkerSpecificAPI = node => node.object.name === 'self' && node.property.type === 'Identifier' && webWorkerSpecificAPIs.has(node.property.name); + /** @param {import('eslint').Rule.RuleContext} context */ const create = context => ({ // ===== Expression ===== /** @param {import('estree').MemberExpression} node */ MemberExpression(node) { - // Allow to use window specify APIs - if (node.object.type === 'Identifier') { - // Check if the identifier is a window specific API - if (node.object.name === 'window' && node.property.type === 'Identifier' && windowSpecificAPIs.has(node.property.name)) { - // Allow to use window.addEventListener/removeEventListener/dispatchEvent with windowSpecificEvents - if (['addEventListener', 'removeEventListener', 'dispatchEvent'].includes(node.property.name)) { - if (node.parent && node.parent.type === 'CallExpression') { - if (node.parent.arguments.length > 0 && node.parent.arguments[0].type === 'Literal' && windowSpecificEvents.has(node.parent.arguments[0].value)) { - return; - } - } else { - return; - } - } else { - return; - } - } - - // Check if the identifier is a web worker specific API - if (node.object.name === 'self' && node.property.type === 'Identifier' && webWorkerSpecificAPIs.has(node.property.name)) { - return; - } + if (node.object.type === 'Identifier' && (isWindowSpecificAPI(node) || isWebWorkerSpecificAPI(node))) { + return; } handleNodes(context, [node.object]); From ffc9b467bb1a3e3f7004d1f21188d2644acbb901 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 31 Jul 2024 14:04:49 +0200 Subject: [PATCH 36/70] Update prefer-global-this.js --- rules/prefer-global-this.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 717602615b..4ab7743f64 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -9,6 +9,7 @@ const messages = { /** Find the variable in the scope. + @param {import('eslint').Scope.Scope} scope @param {string} variableName */ @@ -42,13 +43,15 @@ const windowSpecificEvents = new Set([ ]); /** - * Note: What kind of API should be a windows-specific interfaces? - * it's directly related to window (✅ window.close()) - * it does NOT work well as globalThis.x or x (✅ window.frames, window.top) - * some constructors are occasionally related to window (like Element !== iframe.contentWindow.Element), but they don't need to mention window anyway. - * - * Please use this criterion to decide whether an API should be added here. refs: https://github.com/sindresorhus/eslint-plugin-unicorn/pull/2410#discussion_r1695312427 - */ +Note: What kind of API should be a windows-specific interface? + +1. It's directly related to window (✅ window.close()) +2. It does NOT work well as globalThis.x or x (✅ window.frames, window.top) + +Some constructors are occasionally related to window (like Element !== iframe.contentWindow.Element), but they don't need to mention window anyway. + +Please use these criteria to decide whether an API should be added here. Context: https://github.com/sindresorhus/eslint-plugin-unicorn/pull/2410#discussion_r1695312427 +*/ const windowSpecificAPIs = new Set([ // Properties and methods // https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-window-object @@ -136,6 +139,7 @@ const webWorkerSpecificAPIs = new Set([ /** Report the node with a message. + @param {import('eslint').Rule.RuleContext} context @param {import('estree').Node} node @param {string} value @@ -153,6 +157,7 @@ function report(context, node, value) { /** Handle nodes and check if they should be reported. + @param {import('eslint').Rule.RuleContext} context @param {import('estree').Node | Array} nodes */ @@ -172,7 +177,8 @@ function handleNodes(context, nodes) { } /** -Check if the node is a window specific API +Check if the node is a window-specific API. + @param {import('estree').MemberExpression} node @returns {boolean} */ @@ -194,7 +200,8 @@ const isWindowSpecificAPI = node => { }; /** -Check if the node is a web worker specific API +Check if the node is a web worker specific API. + @param {import('estree').MemberExpression} node @returns {boolean} */ From a105b89c537564d3c79b55790431442ea2d8b4f8 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 5 Aug 2024 09:56:16 +0800 Subject: [PATCH 37/70] reuse GlobalReferenceTracker to simplify the code --- rules/prefer-global-this.js | 189 ++++++++---------------------------- 1 file changed, 40 insertions(+), 149 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 4ab7743f64..05579e63e8 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -1,5 +1,7 @@ 'use strict'; +const {GlobalReferenceTracker} = require('./utils/global-reference-tracker.js'); + const MESSAGE_ID_ERROR = 'prefer-global-this/error'; const MESSAGE_ID_SUGGESTION = 'prefer-global-this/suggestion'; const messages = { @@ -183,6 +185,10 @@ Check if the node is a window-specific API. @returns {boolean} */ const isWindowSpecificAPI = node => { + if (node.type !== 'MemberExpression') { + return false; + } + if (node.object.name !== 'window' || node.property.type !== 'Identifier') { return false; } @@ -205,159 +211,44 @@ Check if the node is a web worker specific API. @param {import('estree').MemberExpression} node @returns {boolean} */ -const isWebWorkerSpecificAPI = node => node.object.name === 'self' && node.property.type === 'Identifier' && webWorkerSpecificAPIs.has(node.property.name); +const isWebWorkerSpecificAPI = node => node.type === 'MemberExpression' && node.object.name === 'self' && node.property.type === 'Identifier' && webWorkerSpecificAPIs.has(node.property.name); /** @param {import('eslint').Rule.RuleContext} context */ -const create = context => ({ - // ===== Expression ===== - - /** @param {import('estree').MemberExpression} node */ - MemberExpression(node) { - if (node.object.type === 'Identifier' && (isWindowSpecificAPI(node) || isWebWorkerSpecificAPI(node))) { - return; - } - - handleNodes(context, [node.object]); - }, - /** @param {import('estree').CallExpression} node */ - CallExpression(node) { - handleNodes(context, [node.object]); - }, - /** @param {import('estree').BinaryExpression} node */ - BinaryExpression(node) { - handleNodes(context, [node.left, node.right]); - }, - /** @param {import('estree').LogicalExpression} node */ - LogicalExpression(node) { - handleNodes(context, [node.left, node.right]); - }, - /** @param {import('estree').ArrayExpression} node */ - ArrayExpression(node) { - handleNodes(context, node.elements); - }, - /** @param {import('estree').AssignmentExpression} node */ - AssignmentExpression(node) { - handleNodes(context, [node.left, node.right]); - }, - /** @param {import('estree').YieldExpression} node */ - YieldExpression(node) { - handleNodes(context, node.argument); - }, - /** @param {import('estree').AwaitExpression} node */ - AwaitExpression(node) { - handleNodes(context, node.argument); - }, - /** @param {import('estree').ConditionalExpression} node */ - ConditionalExpression(node) { - handleNodes(context, [node.test, node.consequent, node.alternate]); - }, - /** @param {import('estree').ImportExpression} node */ - ImportExpression(node) { - handleNodes(context, node.source); - }, - /** @param {import('estree').NewExpression} node */ - NewExpression(node) { - handleNodes(context, node.callee); - }, - /** @param {import('estree').ObjectExpression} node */ - ObjectExpression(node) { - for (const property of node.properties) { - handleNodes(context, property.value); - } - }, - /** @param {import('estree').SequenceExpression} node */ - SequenceExpression(node) { - handleNodes(context, node.expressions); - }, - /** @param {import('estree').TaggedTemplateExpression} node */ - TaggedTemplateExpression(node) { - handleNodes(context, node.tag); - handleNodes(context, node.quasi.expressions); - }, - /** @param {import('estree').TemplateLiteral} node */ - TemplateLiteral(node) { - handleNodes(context, node.expressions); - }, - /** @param {import('estree').UnaryExpression} node */ - UnaryExpression(node) { - handleNodes(context, node.argument); - }, - /** @param {import('estree').UpdateExpression} node */ - UpdateExpression(node) { - handleNodes(context, node.argument); - }, - - // ===== Statements ===== - - /** @param {import('estree').ExpressionStatement} node */ - ExpressionStatement(node) { - switch (node.expression.type) { - case 'Identifier': { - handleNodes(context, node.expression); - break; - } - - default: { - break; +const create = context => { + const tracker = new GlobalReferenceTracker({ + objects: [...globalIdentifier], + handle(reference) { + const {node} = reference; + + switch (node.type) { + case 'Identifier': { + if (isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent)) { + return; + } + + report(context, node, node.name); + break; + } + + default: { + break; + } } - } - }, - /** @param {import('estree').ForStatement} node */ - ForStatement(node) { - handleNodes(context, [node.init, node.test, node.update]); - }, - /** @param {import('estree').ForInStatement} node */ - ForInStatement(node) { - handleNodes(context, [node.left, node.right]); - }, - /** @param {import('estree').ForOfStatement} node */ - ForOfStatement(node) { - handleNodes(context, [node.left, node.right]); - }, - /** @param {import('estree').ReturnStatement} node */ - ReturnStatement(node) { - handleNodes(context, node.argument); - }, - /** @param {import('estree').SwitchStatement} node */ - SwitchStatement(node) { - handleNodes(context, node.discriminant); - - for (const caseNode of node.cases) { - handleNodes(context, caseNode.test); - } - }, - /** @param {import('estree').WhileStatement} node */ - WhileStatement(node) { - handleNodes(context, node.test); - }, - /** @param {import('estree').DoWhileStatement} node */ - DoWhileStatement(node) { - handleNodes(context, node.test); - }, - /** @param {import('estree').IfStatement} node */ - IfStatement(node) { - handleNodes(context, node.test); - }, - /** @param {import('estree').ThrowStatement} node */ - ThrowStatement(node) { - handleNodes(context, node.argument); - }, - /** @param {import('estree').TryStatement} node */ - TryStatement(_node) {}, - /** @param {import('estree').CatchClause} node */ - CatchClause(_node) {}, - - // ===== Declarations ===== + }, + }); - /** @param {import('estree').VariableDeclarator} node */ - VariableDeclarator(node) { - handleNodes(context, node.init); - }, - /** @param {import('estree').AssignmentPattern} node */ - AssignmentPattern(node) { - handleNodes(context, node.right); - }, -}); + return { + ...tracker.createListeners(context), + /** @param {import('estree').AssignmentExpression} node */ + AssignmentExpression(node) { + handleNodes(context, [node.left]); + }, + /** @param {import('estree').UpdateExpression} node */ + UpdateExpression(node) { + handleNodes(context, node.argument); + }, + }; +}; /** @type {import('eslint').Rule.RuleModule} */ module.exports = { From 91cd64364f08181a43bd9fd37f07493c00870a94 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 5 Aug 2024 10:08:17 +0800 Subject: [PATCH 38/70] re-trigger ci --- rules/prefer-global-this.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 05579e63e8..5cd3592417 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -216,7 +216,7 @@ const isWebWorkerSpecificAPI = node => node.type === 'MemberExpression' && node. /** @param {import('eslint').Rule.RuleContext} context */ const create = context => { const tracker = new GlobalReferenceTracker({ - objects: [...globalIdentifier], + objects: globalIdentifier, handle(reference) { const {node} = reference; From 8cc0c791664c9d1bd3c57dd47023cf6cbf5e3f9f Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 5 Aug 2024 16:58:21 +0800 Subject: [PATCH 39/70] docs: update update docs docs: updat --- docs/rules/prefer-global-this.md | 79 +++++++++++++++++++++----------- test/package.mjs | 1 + 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index 786d9ff1ec..bc71dd1c6a 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -11,39 +11,66 @@ This rule will enforce the use of `globalThis` over `window`, `self`, and `globa However, some window-specific APIs are still allowed (e.g. `window.innerWidth`, `window.innerHeight`). You can find the list of APIs in the [source code](../../rules/prefer-global-this.js) of this rule. -## Fail +## Examples ```js -window -window.foo -window[foo] -window.foo() -global -global.foo -global[foo] -global.foo() -const {foo} = window -const {foo} = global +window; // ❌ +globalThis; // ✅ +``` -window.addEventListener('click', () => {}) -window.location -window.navigator +```js +window.foo; // ❌ +globalThis.foo; // ✅ ``` -## Pass +```js +window[foo]; // ❌ +globalThis[foo]; // ✅ +``` ```js -// Window specific APIs -window.innerWidth -window.innerHeight +global; // ❌ +globalThis; // ✅ +``` -// Worker specific APIs -self.postMessage('Hello') -self.onmessage = () => {} +```js +global.foo; // ❌ +globalThis.foo; // ✅ +``` + +```js +global[foo]; // ❌ +globalThis[foo]; // ✅ +``` + +```js +const { foo } = window; // ❌ +const { foo } = globalThis; // ✅ +``` + +```js +window.location; // ❌ +globalThis.location; // ✅ + +window.innerWidth; // ✅ (Window specific API) +window.innerHeight; // ✅ (Window specific API) +``` + +```js +window.navigator; // ❌ +globalThis.navigator; // ✅ +``` + +```js +self.postMessage('Hello') // ✅ (Web Worker specific API) +self.onmessage = () => {} // ✅ (Web Worker specific API) +``` + +```js +window.addEventListener("click", () => {}); // ❌ +globalThis.addEventListener("click", () => {}); // ✅ -globalThis -globalThis.foo -globalThis[foo] -globalThis.foo() -const {foo} = globalThis +window.addEventListener("resize", () => {}); // ✅ (Window specific event) +window.addEventListener("load", () => {}); // ✅ (Window specific event) +window.addEventListener("unload", () => {}); // ✅ (Window specific event) ``` diff --git a/test/package.mjs b/test/package.mjs index 7434537ca7..97c6cf68ef 100644 --- a/test/package.mjs +++ b/test/package.mjs @@ -31,6 +31,7 @@ const RULES_WITHOUT_PASS_FAIL_SECTIONS = new Set([ // Intended to not use `pass`/`fail` section in this rule. 'prefer-modern-math-apis', 'prefer-math-min-max', + 'prefer-global-this', ]); test('Every rule is defined in index file in alphabetical order', t => { From 8678b45b969e247262b3dfed4b4ff5c27099a99b Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 5 Aug 2024 12:40:10 +0200 Subject: [PATCH 40/70] Update prefer-global-this.md --- docs/rules/prefer-global-this.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index bc71dd1c6a..f34f4de2eb 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -44,8 +44,8 @@ globalThis[foo]; // ✅ ``` ```js -const { foo } = window; // ❌ -const { foo } = globalThis; // ✅ +const {foo} = window; // ❌ +const {foo} = globalThis; // ✅ ``` ```js @@ -62,15 +62,15 @@ globalThis.navigator; // ✅ ``` ```js -self.postMessage('Hello') // ✅ (Web Worker specific API) -self.onmessage = () => {} // ✅ (Web Worker specific API) +self.postMessage('Hello'); // ✅ (Web Worker specific API) +self.onmessage = () => {}; // ✅ (Web Worker specific API) ``` ```js -window.addEventListener("click", () => {}); // ❌ -globalThis.addEventListener("click", () => {}); // ✅ +window.addEventListener('click', () => {}); // ❌ +globalThis.addEventListener('click', () => {}); // ✅ -window.addEventListener("resize", () => {}); // ✅ (Window specific event) -window.addEventListener("load", () => {}); // ✅ (Window specific event) -window.addEventListener("unload", () => {}); // ✅ (Window specific event) +window.addEventListener('resize', () => {}); // ✅ (Window specific event) +window.addEventListener('load', () => {}); // ✅ (Window specific event) +window.addEventListener('unload', () => {}); // ✅ (Window specific event) ``` From c83eb91d710646a22ac96fced025d49a25c6e2af Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 6 Aug 2024 00:23:11 +0800 Subject: [PATCH 41/70] Remove unnecessary switch --- rules/prefer-global-this.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 5cd3592417..94656b1f8b 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -220,19 +220,12 @@ const create = context => { handle(reference) { const {node} = reference; - switch (node.type) { - case 'Identifier': { - if (isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent)) { - return; - } - - report(context, node, node.name); - break; + if (node.type === 'Identifier') { + if (isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent)) { + return; } - default: { - break; - } + report(context, node, node.name); } }, }); From cd0dacb2e0a53fafb591879b424474726d7417f5 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 6 Aug 2024 17:33:51 +0800 Subject: [PATCH 42/70] update prefer-global-this.md --- docs/rules/prefer-global-this.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index f34f4de2eb..2e44ccb0e0 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -9,7 +9,12 @@ This rule will enforce the use of `globalThis` over `window`, `self`, and `global`. -However, some window-specific APIs are still allowed (e.g. `window.innerWidth`, `window.innerHeight`). You can find the list of APIs in the [source code](../../rules/prefer-global-this.js) of this rule. +However, there are several exceptions that remain permitted: + +1. Certain window/WebWorker-specific APIs, such as `window.innerHeight` and `self.postMessage` +2. Window-specific events, such as `window.addEventListener('resize')` + +The complete list of permitted APIs can be found in the rule's [source code](../../rules/prefer-global-this.js). ## Examples From dcaccbb73757cc27816dae6571ba2a68c1af21eb Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 9 Aug 2024 09:52:22 +0800 Subject: [PATCH 43/70] refactor: Replace `{{value}}` with `globalThis` in prefer-global-this.js https://github.com/sindresorhus/eslint-plugin-unicorn/pull/2410#discussion_r1710049556 --- rules/prefer-global-this.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 94656b1f8b..12cd3e7418 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -5,8 +5,8 @@ const {GlobalReferenceTracker} = require('./utils/global-reference-tracker.js'); const MESSAGE_ID_ERROR = 'prefer-global-this/error'; const MESSAGE_ID_SUGGESTION = 'prefer-global-this/suggestion'; const messages = { - [MESSAGE_ID_ERROR]: 'Prefer `{{replacement}}` over `{{value}}`.', - [MESSAGE_ID_SUGGESTION]: 'Replace `{{value}}` with `{{replacement}}`.', + [MESSAGE_ID_ERROR]: 'Prefer `globalThis` over `{{value}}`.', + [MESSAGE_ID_SUGGESTION]: 'Replace `{{value}}` with `globalThis`.', }; /** @@ -151,9 +151,9 @@ function report(context, node, value) { context.report({ node, messageId: MESSAGE_ID_ERROR, - data: {value, replacement: 'globalThis'}, + data: {value}, fix, - suggest: [{messageId: MESSAGE_ID_SUGGESTION, data: {value, replacement: 'globalThis'}, fix}], + suggest: [{messageId: MESSAGE_ID_SUGGESTION, data: {value}, fix}], }); } From 5e85ec35ffeb16cbf0c0d969fc48b177fbf90df4 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 9 Aug 2024 09:54:59 +0800 Subject: [PATCH 44/70] refactor: Simplify window-specific API check in prefer-global-this.js https://github.com/sindresorhus/eslint-plugin-unicorn/pull/2410#discussion_r1710025209 --- rules/prefer-global-this.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 12cd3e7418..bd554ec286 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -194,7 +194,7 @@ const isWindowSpecificAPI = node => { } if (windowSpecificAPIs.has(node.property.name)) { - if (['addEventListener', 'removeEventListener', 'dispatchEvent'].includes(node.property.name) && node.parent && node.parent.type === 'CallExpression') { + if (['addEventListener', 'removeEventListener', 'dispatchEvent'].includes(node.property.name) && node.parent.type === 'CallExpression' && node.parent.callee === node) { const argument = node.parent.arguments[0]; return argument && argument.type === 'Literal' && windowSpecificEvents.has(argument.value); } From 8fe496a28d3ecae61646a8a4c77e132d9859c015 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 9 Aug 2024 09:56:40 +0800 Subject: [PATCH 45/70] refactor: remove unnecessary condition in for of nodes --- rules/prefer-global-this.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index bd554ec286..9cacbd1e9c 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -169,7 +169,7 @@ function handleNodes(context, nodes) { } for (const node of nodes) { - if (node && node.type === 'Identifier' && globalIdentifier.has(node.name)) { + if (node.type === 'Identifier' && globalIdentifier.has(node.name)) { const variable = findVariableInScope(context.sourceCode.getScope(node), node.name); if (!variable) { report(context, node, node.name); From 3b8e20f00518121d0d7dfc39896587590560e675 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 9 Aug 2024 10:05:13 +0800 Subject: [PATCH 46/70] chore: Remove unnecessary suggestion message in prefer-global-this.js https://github.com/sindresorhus/eslint-plugin-unicorn/pull/2410#discussion_r1710053471 --- rules/prefer-global-this.js | 5 +- test/snapshots/prefer-global-this.mjs.md | 235 --------------------- test/snapshots/prefer-global-this.mjs.snap | Bin 2720 -> 2336 bytes 3 files changed, 1 insertion(+), 239 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 9cacbd1e9c..fb7516b5ba 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -3,10 +3,8 @@ const {GlobalReferenceTracker} = require('./utils/global-reference-tracker.js'); const MESSAGE_ID_ERROR = 'prefer-global-this/error'; -const MESSAGE_ID_SUGGESTION = 'prefer-global-this/suggestion'; const messages = { [MESSAGE_ID_ERROR]: 'Prefer `globalThis` over `{{value}}`.', - [MESSAGE_ID_SUGGESTION]: 'Replace `{{value}}` with `globalThis`.', }; /** @@ -153,7 +151,6 @@ function report(context, node, value) { messageId: MESSAGE_ID_ERROR, data: {value}, fix, - suggest: [{messageId: MESSAGE_ID_SUGGESTION, data: {value}, fix}], }); } @@ -253,7 +250,7 @@ module.exports = { recommended: true, }, fixable: 'code', - hasSuggestions: true, + hasSuggestions: false, messages, }, }; diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 5fd0892851..2959a5a31b 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -23,10 +23,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | global␊ | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`global\` with \`globalThis\`.␊ - 1 | globalThis␊ ` ## invalid(2): self @@ -48,10 +44,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | self␊ | ^^^^ Prefer \`globalThis\` over \`self\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ - 1 | globalThis␊ ` ## invalid(3): window @@ -73,10 +65,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis␊ ` ## invalid(4): window.foo @@ -98,10 +86,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window.foo␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.foo␊ ` ## invalid(5): window[foo] @@ -123,10 +107,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window[foo]␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis[foo]␊ ` ## invalid(6): window.foo() @@ -148,10 +128,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window.foo()␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.foo()␊ ` ## invalid(7): window > 10 @@ -173,10 +149,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window > 10␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis > 10␊ ` ## invalid(8): 10 > window @@ -198,10 +170,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | 10 > window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | 10 > globalThis␊ ` ## invalid(9): window ?? 10 @@ -223,10 +191,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window ?? 10␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis ?? 10␊ ` ## invalid(10): 10 ?? window @@ -248,10 +212,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | 10 ?? window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | 10 ?? globalThis␊ ` ## invalid(11): window.foo = 123 @@ -273,10 +233,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window.foo = 123␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.foo = 123␊ ` ## invalid(12): window = 123 @@ -298,10 +254,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window = 123␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis = 123␊ ` ## invalid(13): obj.a = window @@ -323,10 +275,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | obj.a = window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | obj.a = globalThis␊ ` ## invalid(14): function* gen() { yield window } @@ -354,12 +302,6 @@ Generated by [AVA](https://avajs.dev). > 2 | yield window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 3 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | function* gen() {␊ - 2 | yield globalThis␊ - 3 | }␊ ` ## invalid(15): async function gen() { await window } @@ -387,12 +329,6 @@ Generated by [AVA](https://avajs.dev). > 2 | await window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 3 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | async function gen() {␊ - 2 | await globalThis␊ - 3 | }␊ ` ## invalid(16): window ? foo : bar @@ -414,10 +350,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window ? foo : bar␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis ? foo : bar␊ ` ## invalid(17): foo ? window : bar @@ -439,10 +371,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | foo ? window : bar␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | foo ? globalThis : bar␊ ` ## invalid(18): foo ? bar : window @@ -464,10 +392,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | foo ? bar : window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | foo ? bar : globalThis␊ ` ## invalid(19): function foo() { return window } @@ -495,12 +419,6 @@ Generated by [AVA](https://avajs.dev). > 2 | return window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 3 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | function foo() {␊ - 2 | return globalThis␊ - 3 | }␊ ` ## invalid(20): new window() @@ -522,10 +440,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | new window()␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | new globalThis()␊ ` ## invalid(21): const obj = { foo: window.foo, bar: window.bar, window: window } @@ -559,14 +473,6 @@ Generated by [AVA](https://avajs.dev). 3 | bar: window.bar,␊ 4 | window: window␊ 5 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | const obj = {␊ - 2 | foo: globalThis.foo,␊ - 3 | bar: window.bar,␊ - 4 | window: window␊ - 5 | }␊ ` > Error 2/3 @@ -578,14 +484,6 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 4 | window: window␊ 5 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | const obj = {␊ - 2 | foo: window.foo,␊ - 3 | bar: globalThis.bar,␊ - 4 | window: window␊ - 5 | }␊ ` > Error 3/3 @@ -597,14 +495,6 @@ Generated by [AVA](https://avajs.dev). > 4 | window: window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 5 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | const obj = {␊ - 2 | foo: window.foo,␊ - 3 | bar: window.bar,␊ - 4 | window: globalThis␊ - 5 | }␊ ` ## invalid(22): function sequenceTest() { let x, y; x = (y = 10, y + 5, window); console.log(x, y); } @@ -638,14 +528,6 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 4 | console.log(x, y);␊ 5 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | function sequenceTest() {␊ - 2 | let x, y;␊ - 3 | x = (y = 10, y + 5, globalThis);␊ - 4 | console.log(x, y);␊ - 5 | }␊ ` ## invalid(23): window`Hello ${42} World` @@ -667,10 +549,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window\`Hello ${42} World\`␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis\`Hello ${42} World\`␊ ` ## invalid(24): tag`Hello ${window.foo} World` @@ -692,10 +570,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | tag\`Hello ${window.foo} World\`␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | tag\`Hello ${globalThis.foo} World\`␊ ` ## invalid(25): var str = `hello ${window.foo} world!` @@ -717,10 +591,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | var str = \`hello ${window.foo} world!\`␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | var str = \`hello ${globalThis.foo} world!\`␊ ` ## invalid(26): delete window.foo @@ -742,10 +612,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | delete window.foo␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | delete globalThis.foo␊ ` ## invalid(27): ++window @@ -767,10 +633,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | ++window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | ++globalThis␊ ` ## invalid(28): ++window.foo @@ -792,10 +654,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | ++window.foo␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | ++globalThis.foo␊ ` ## invalid(29): for (var attr in window) { } @@ -823,12 +681,6 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 2 |␊ 3 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | for (var attr in globalThis) {␊ - 2 |␊ - 3 | }␊ ` ## invalid(30): for (window.foo = 0; i < 10; window.foo++) { } @@ -856,12 +708,6 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 2 |␊ 3 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | for (globalThis.foo = 0; i < 10; window.foo++) {␊ - 2 |␊ - 3 | }␊ ` > Error 2/2 @@ -871,12 +717,6 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 2 |␊ 3 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | for (window.foo = 0; i < 10; globalThis.foo++) {␊ - 2 |␊ - 3 | }␊ ` ## invalid(31): for (const item of window.foo) { } @@ -901,11 +741,6 @@ Generated by [AVA](https://avajs.dev). > 1 | for (const item of window.foo) {␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 2 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | for (const item of globalThis.foo) {␊ - 2 | }␊ ` ## invalid(32): for (const item of window) { } @@ -930,11 +765,6 @@ Generated by [AVA](https://avajs.dev). > 1 | for (const item of window) {␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 2 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | for (const item of globalThis) {␊ - 2 | }␊ ` ## invalid(33): switch (window) {} @@ -956,10 +786,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | switch (window) {}␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | switch (globalThis) {}␊ ` ## invalid(34): switch (true) { case window: break; } @@ -990,13 +816,6 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 3 | break;␊ 4 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | switch (true) {␊ - 2 | case globalThis:␊ - 3 | break;␊ - 4 | }␊ ` ## invalid(35): switch (true) { case window.foo: break; } @@ -1027,13 +846,6 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 3 | break;␊ 4 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | switch (true) {␊ - 2 | case globalThis.foo:␊ - 3 | break;␊ - 4 | }␊ ` ## invalid(36): while (window) { } @@ -1058,11 +870,6 @@ Generated by [AVA](https://avajs.dev). > 1 | while (window) {␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 2 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | while (globalThis) {␊ - 2 | }␊ ` ## invalid(37): do {} while (window) {} @@ -1084,10 +891,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | do {} while (window) {}␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | do {} while (globalThis) {}␊ ` ## invalid(38): if (window) {} @@ -1109,10 +912,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | if (window) {}␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | if (globalThis) {}␊ ` ## invalid(39): throw window @@ -1134,10 +933,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | throw window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | throw globalThis␊ ` ## invalid(40): var foo = window @@ -1159,10 +954,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | var foo = window␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | var foo = globalThis␊ ` ## invalid(41): function foo (name = window) { } @@ -1190,12 +981,6 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ 2 |␊ 3 | }␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | function foo (name = globalThis) {␊ - 2 |␊ - 3 | }␊ ` ## invalid(42): self.innerWidth @@ -1217,10 +1002,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | self.innerWidth␊ | ^^^^ Prefer \`globalThis\` over \`self\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ - 1 | globalThis.innerWidth␊ ` ## invalid(43): self.innerHeight @@ -1242,10 +1023,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | self.innerHeight␊ | ^^^^ Prefer \`globalThis\` over \`self\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`self\` with \`globalThis\`.␊ - 1 | globalThis.innerHeight␊ ` ## invalid(44): window.crypto @@ -1267,10 +1044,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window.crypto␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.crypto␊ ` ## invalid(45): window.addEventListener("play", () => {}) @@ -1292,10 +1065,6 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window.addEventListener("play", () => {})␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.addEventListener("play", () => {})␊ ` ## invalid(46): window.onplay = function () {} @@ -1317,8 +1086,4 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | window.onplay = function () {}␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ␊ - --------------------------------------------------------------------------------␊ - Suggestion 1/1: Replace \`window\` with \`globalThis\`.␊ - 1 | globalThis.onplay = function () {}␊ ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 35533dfdc607f9c991146316414efce6415c96eb..83baa35e982063e6855e4b020473b78f067a8591 100644 GIT binary patch literal 2336 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 a?oY@<<*FcB&{rxJz<&Xg_6XRCUH||k09Atk From 18e1f1b5f657a99e71042096040fc76407a6288e Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 9 Aug 2024 10:15:38 +0800 Subject: [PATCH 47/70] test: add test case --- test/prefer-global-this.mjs | 1 + test/snapshots/prefer-global-this.mjs.md | 103 +++++++++++++-------- test/snapshots/prefer-global-this.mjs.snap | Bin 2336 -> 2363 bytes 3 files changed, 63 insertions(+), 41 deletions(-) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 47db742630..f2ce2a54c9 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -61,6 +61,7 @@ test.snapshot({ 'window', 'window.foo', 'window[foo]', + 'window["foo"]', 'window.foo()', 'window > 10', '10 > window', diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 2959a5a31b..2944ab1d3b 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -109,7 +109,28 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(6): window.foo() +## invalid(6): window["foo"] + +> Input + + `␊ + 1 | window["foo"]␊ + ` + +> Output + + `␊ + 1 | globalThis["foo"]␊ + ` + +> Error 1/1 + + `␊ + > 1 | window["foo"]␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ` + +## invalid(7): window.foo() > Input @@ -130,7 +151,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(7): window > 10 +## invalid(8): window > 10 > Input @@ -151,7 +172,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(8): 10 > window +## invalid(9): 10 > window > Input @@ -172,7 +193,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(9): window ?? 10 +## invalid(10): window ?? 10 > Input @@ -193,7 +214,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(10): 10 ?? window +## invalid(11): 10 ?? window > Input @@ -214,7 +235,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(11): window.foo = 123 +## invalid(12): window.foo = 123 > Input @@ -235,7 +256,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(12): window = 123 +## invalid(13): window = 123 > Input @@ -256,7 +277,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(13): obj.a = window +## invalid(14): obj.a = window > Input @@ -277,7 +298,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(14): function* gen() { yield window } +## invalid(15): function* gen() { yield window } > Input @@ -304,7 +325,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(15): async function gen() { await window } +## invalid(16): async function gen() { await window } > Input @@ -331,7 +352,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(16): window ? foo : bar +## invalid(17): window ? foo : bar > Input @@ -352,7 +373,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(17): foo ? window : bar +## invalid(18): foo ? window : bar > Input @@ -373,7 +394,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(18): foo ? bar : window +## invalid(19): foo ? bar : window > Input @@ -394,7 +415,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(19): function foo() { return window } +## invalid(20): function foo() { return window } > Input @@ -421,7 +442,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(20): new window() +## invalid(21): new window() > Input @@ -442,7 +463,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(21): const obj = { foo: window.foo, bar: window.bar, window: window } +## invalid(22): const obj = { foo: window.foo, bar: window.bar, window: window } > Input @@ -497,7 +518,7 @@ Generated by [AVA](https://avajs.dev). 5 | }␊ ` -## invalid(22): function sequenceTest() { let x, y; x = (y = 10, y + 5, window); console.log(x, y); } +## invalid(23): function sequenceTest() { let x, y; x = (y = 10, y + 5, window); console.log(x, y); } > Input @@ -530,7 +551,7 @@ Generated by [AVA](https://avajs.dev). 5 | }␊ ` -## invalid(23): window`Hello ${42} World` +## invalid(24): window`Hello ${42} World` > Input @@ -551,7 +572,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(24): tag`Hello ${window.foo} World` +## invalid(25): tag`Hello ${window.foo} World` > Input @@ -572,7 +593,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(25): var str = `hello ${window.foo} world!` +## invalid(26): var str = `hello ${window.foo} world!` > Input @@ -593,7 +614,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(26): delete window.foo +## invalid(27): delete window.foo > Input @@ -614,7 +635,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(27): ++window +## invalid(28): ++window > Input @@ -635,7 +656,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(28): ++window.foo +## invalid(29): ++window.foo > Input @@ -656,7 +677,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(29): for (var attr in window) { } +## invalid(30): for (var attr in window) { } > Input @@ -683,7 +704,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(30): for (window.foo = 0; i < 10; window.foo++) { } +## invalid(31): for (window.foo = 0; i < 10; window.foo++) { } > Input @@ -719,7 +740,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(31): for (const item of window.foo) { } +## invalid(32): for (const item of window.foo) { } > Input @@ -743,7 +764,7 @@ Generated by [AVA](https://avajs.dev). 2 | }␊ ` -## invalid(32): for (const item of window) { } +## invalid(33): for (const item of window) { } > Input @@ -767,7 +788,7 @@ Generated by [AVA](https://avajs.dev). 2 | }␊ ` -## invalid(33): switch (window) {} +## invalid(34): switch (window) {} > Input @@ -788,7 +809,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(34): switch (true) { case window: break; } +## invalid(35): switch (true) { case window: break; } > Input @@ -818,7 +839,7 @@ Generated by [AVA](https://avajs.dev). 4 | }␊ ` -## invalid(35): switch (true) { case window.foo: break; } +## invalid(36): switch (true) { case window.foo: break; } > Input @@ -848,7 +869,7 @@ Generated by [AVA](https://avajs.dev). 4 | }␊ ` -## invalid(36): while (window) { } +## invalid(37): while (window) { } > Input @@ -872,7 +893,7 @@ Generated by [AVA](https://avajs.dev). 2 | }␊ ` -## invalid(37): do {} while (window) {} +## invalid(38): do {} while (window) {} > Input @@ -893,7 +914,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(38): if (window) {} +## invalid(39): if (window) {} > Input @@ -914,7 +935,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(39): throw window +## invalid(40): throw window > Input @@ -935,7 +956,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(40): var foo = window +## invalid(41): var foo = window > Input @@ -956,7 +977,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(41): function foo (name = window) { } +## invalid(42): function foo (name = window) { } > Input @@ -983,7 +1004,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(42): self.innerWidth +## invalid(43): self.innerWidth > Input @@ -1004,7 +1025,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^ Prefer \`globalThis\` over \`self\`.␊ ` -## invalid(43): self.innerHeight +## invalid(44): self.innerHeight > Input @@ -1025,7 +1046,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^ Prefer \`globalThis\` over \`self\`.␊ ` -## invalid(44): window.crypto +## invalid(45): window.crypto > Input @@ -1046,7 +1067,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(45): window.addEventListener("play", () => {}) +## invalid(46): window.addEventListener("play", () => {}) > Input @@ -1067,7 +1088,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(46): window.onplay = function () {} +## invalid(47): window.onplay = function () {} > Input diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 83baa35e982063e6855e4b020473b78f067a8591..3f7d4ba93a30da4209a08a21ab1357f2c7390b5d 100644 GIT binary patch literal 2363 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 literal 2336 zcmV+*3E%cXRzVc?#$iozDEjD4r@!FPS_g!nPzv>13AD(x+R$$#b{OZK( z6a2UDwTZX)y*UX`g`M!}N#=CG^o+IkQ^59s-K(DS!f?S6>qeYqaQplb-!nrz8N z004I2!QclseAZ(=EXRb);BCZzSuTeL?90CI`B0s%hS9D?(bkGh=rgCM#(D_3@kZ!7 ze>S&BuOQG|80o-79A`?D{7HR`BBS+U6Eus85bolfO&S+@FFr&k#_0eub(KbZ1 z<(}uM5z`UG2rBAR2=jpwwS>cw-$1~NDDnX)r|37M=x0RqU-vxk8#Vmn$fI{r_yY(P z|7isJP>Ej#VgYU<t%Hm) z*I|gtD2aOr`gvRuu|cUOa!})lP@{@QNmzhtt*$CU$CkuVs+>j0!{lg*&?e2I7|y>+ zYH_z{G)e6itsa@(qSqp|Tk_T6BcTJIG1A)-?F6>xo`n_W7K*S9TQ+mLQA&1Ir9MMW&xR2zJd*&mf!{LU zBtRW@V3$&I3Gp@!c_oE0H&%KFk-J**7VY$S8Nd#ynW%|O@TsoV-*P*`C6Nwm)3Sq< zbX-M|&4-cEWI{WcG%Y9B5&7aM>?X7=Urhx) z7N|%{=_!OgO3XkMyvh5QFrL@=8tcR7=bS%!(T}E&iZs_}h?P{*>+=8++z9m{jORN` ziB*~tDzz;i^xGI|D#^%ERT^S5-bh_Ua0jV`jN`7$`^|J-dNaXbQ3>1NvtZqK$9^+K zJYt+eeB-~Fbi9TG;4UKfbmT3K(sC$mu-d?&9@+AjQJ#zqhhx;TM+bw z8X1g**?U=D7h3RzM#ppe0iUD60&Mg2$ZL-&-X!7=ZOfku|J@|Y_E{Lt6BJG-R07!v zYiobfT$soGNvo3p4gPm*d=g+rSL1XU>Yc!=AMA+qf0Q$*F=n)l@we>JE5A>WF156} z@ci!|t1HG+Q`Aj;6#sR3ZD~CjFD_&MYr_A3kpF*-=D$wKmd2Afsu2StLa0yIqtq6h~f5j*`%hZ(Rh|iZB+BJ$eBf$m=s<^yw^=igSqPEWv|cj;T_v zA+mNTWrkBPV)9)V+Vaha4ah~=yTlFugyu3(`BKHCA}i( z1(~dXwis?B=#_*Ds1Ek7L{TU)*d_3MDDc*`g1`qmS{d_69Wga)AxA4>e?-SIoMEKx z4O~Qw4IQI2JJPV43{k0$lEcy{GaA(=Rs4Bz5vLM~j}Edb^I*dTs8;5sL7-Ghq~k|T z_ekOyvSueJxi2c&P)_h9JNWA!D0z+ROtQ-NXyjGJx@unS1B{^ zdMzypngldaTvJ&I$PnK+oy4GPxCxsf{7VvDoE_BpQn9~j2c6ZZRg17q2u+_Is7Uj( zg9wYXq(xjt1h=9qpsI1m`9xcsqt+XePJzG9cs+Kkel#O(LfdE7BXZY!+JlI&&Cv9{= zCEgJdM^7Tm5@%owCy(Bx%T8Wo=p`gD9+?Jb8FHnd;#0_V0%}wO{jMcIejcztsUYaj@!p(MhQ3 z-hhlT-y0aB#<~}Z48n`K7uu+V8=1pZjZP6dwj|E{UTBQWP==l_DTb46l;b^%Mm2HI z0t&A6mQCR>Pr%GKeWj_20yp{aA!!)){=Jvf#C4>|60=uU1Jfo>;>NjnN8nAaG%Kd_ zQ00(NMfx(V<8Q46#4hkj Date: Fri, 9 Aug 2024 10:18:51 +0800 Subject: [PATCH 48/70] refactor: use isShadowed to found shadowed variable https://github.com/sindresorhus/eslint-plugin-unicorn/pull/2410#discussion_r1710563927 --- rules/prefer-global-this.js | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index fb7516b5ba..0ecddb00ad 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -1,27 +1,13 @@ 'use strict'; const {GlobalReferenceTracker} = require('./utils/global-reference-tracker.js'); +const isShadowed = require('./utils/is-shadowed.js'); const MESSAGE_ID_ERROR = 'prefer-global-this/error'; const messages = { [MESSAGE_ID_ERROR]: 'Prefer `globalThis` over `{{value}}`.', }; -/** -Find the variable in the scope. - -@param {import('eslint').Scope.Scope} scope -@param {string} variableName -*/ -const findVariableInScope = (scope, variableName) => { - if (!scope || scope.type === 'global') { - return; - } - - const variable = scope.variables.find(variable => variable.name === variableName); - return variable || findVariableInScope(scope.upper, variableName); -}; - const globalIdentifier = new Set(['window', 'self', 'global']); const windowSpecificEvents = new Set([ @@ -166,11 +152,8 @@ function handleNodes(context, nodes) { } for (const node of nodes) { - if (node.type === 'Identifier' && globalIdentifier.has(node.name)) { - const variable = findVariableInScope(context.sourceCode.getScope(node), node.name); - if (!variable) { - report(context, node, node.name); - } + if (node.type === 'Identifier' && globalIdentifier.has(node.name) && !isShadowed(context.sourceCode.getScope(node), node)) { + report(context, node, node.name); } } } From ac7a9b8e026307774c28e0f50ce864f5543b7683 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 9 Aug 2024 10:25:54 +0800 Subject: [PATCH 49/70] fix: eslint-docs --- docs/rules/prefer-global-this.md | 2 +- readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index 2e44ccb0e0..5f834d52d2 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -2,7 +2,7 @@ 💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs-eslintconfigjs). -🔧💡 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) and manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). +🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix). diff --git a/readme.md b/readme.md index 9013888417..c6ba4179b3 100644 --- a/readme.md +++ b/readme.md @@ -189,7 +189,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c | [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. | ✅ | | 💡 | | [prefer-event-target](docs/rules/prefer-event-target.md) | Prefer `EventTarget` over `EventEmitter`. | ✅ | | | | [prefer-export-from](docs/rules/prefer-export-from.md) | Prefer `export…from` when re-exporting. | ✅ | 🔧 | 💡 | -| [prefer-global-this](docs/rules/prefer-global-this.md) | Prefer `globalThis` over `window`, `self`, and `global`. | ✅ | 🔧 | 💡 | +| [prefer-global-this](docs/rules/prefer-global-this.md) | Prefer `globalThis` over `window`, `self`, and `global`. | ✅ | 🔧 | | | [prefer-includes](docs/rules/prefer-includes.md) | Prefer `.includes()` over `.indexOf()`, `.lastIndexOf()`, and `Array#some()` when checking for existence or non-existence. | ✅ | 🔧 | 💡 | | [prefer-json-parse-buffer](docs/rules/prefer-json-parse-buffer.md) | Prefer reading a JSON file as a buffer. | | 🔧 | | | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | ✅ | 🔧 | | From d5a63e77a7f2e02d34ce0f4abe0215f2491e06b3 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Fri, 9 Aug 2024 10:35:41 +0800 Subject: [PATCH 50/70] test: add test case for AssignmentPattern --- test/prefer-global-this.mjs | 1 + test/snapshots/prefer-global-this.mjs.md | 21 +++++++++++++++++++++ test/snapshots/prefer-global-this.mjs.snap | Bin 2363 -> 2416 bytes 3 files changed, 22 insertions(+) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index f2ce2a54c9..f3c4f65d61 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -160,6 +160,7 @@ test.snapshot({ 'window.crypto', 'window.addEventListener("play", () => {})', 'window.onplay = function () {}', + 'function greet({ name = window.foo }) {}', ], }); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 2944ab1d3b..68b78b6658 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -1108,3 +1108,24 @@ Generated by [AVA](https://avajs.dev). > 1 | window.onplay = function () {}␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` + +## invalid(48): function greet({ name = window.foo }) {} + +> Input + + `␊ + 1 | function greet({ name = window.foo }) {}␊ + ` + +> Output + + `␊ + 1 | function greet({ name = globalThis.foo }) {}␊ + ` + +> Error 1/1 + + `␊ + > 1 | function greet({ name = window.foo }) {}␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 3f7d4ba93a30da4209a08a21ab1357f2c7390b5d..f2f018080fcabca8cebe57a11d7db21beb9b318b 100644 GIT binary patch literal 2416 zcmV-$36J(cRzVEma0i4CLdArzn|0Q^v+Izo@%jV=1;k5$ zh(scQXLoz;fnmm(9ow;N3!UybB);$!By`g835nmpKj259-kt90ny#MdSx?wcku%Rz zRZn&GOZCkE#{)kcel_{A^$Ux=*k_R!?76--swA;H-I;8M@#NpXj7Dzk z-Z}g5!lMiP_s}B?Pd@bcB0w9ClBXA$?+%#H-VSzl!(lyDQmz4R}e&BTCrJ&M8z+AHlO+8q(CQ}4lq`C~oS zGsum{65si=l|}j%0$oiaotjAF%!!geX^v55v{UcFz88$becO!Ao_@d?O^jG(boR74 z+C33%S4P_$hoK%Z9YKnqqP~DI&uCFAI2`#+1biJuJ_S`2{l18PRYw2mI1E42!#|Ha z`a24L3ZdeE8G)YF;#YxKfDaM!4J5z}RgnVspA!;XNhMeshv5<-!b`}jr?Ch#5GBJa z2=<&V1A<~9K1SHJ)o7wV zjEOr4`c66~QiIB%s6dSuq#6#ICSe`gPDfXSjxCF$RJnwZXUXXjp>3)~GhF>BNjHur zO>(Qns7GP7n6=2QmTGl)Uh2TNl;PmZrVH!FdZD+77)5DOL%1^;TtUs;Md0@nH8Muk zs;Q!GE=yhbW^=q73}Y`0F2NQHYIQh-1CRM5k&>bJ_b2+)Be zIHr`mfp~kCyo$n@8!LT;$O9vJpLTk_3}A=!OgJ(Ve9!An4uYX{Nv6ZycfB|#9dDz^ z){@9*GO3+PnwOLJ5cx(Ka?8a03t5=tTjHiMeGfv#*l!{^Ds|h?gP=Fm$Y3hW z$%o~8QVV|27>2YJfBR{Hbg6IDh3Eg& zTvaijnsVH9%J^@}Yv1U}d~sR(?@0fDL;n9<&VQ4VeS;@yR3!r=Lg=h?MClG>>2}l= zWy0?5vS7$=u}M5#T6`A6{be{Z7stAG+PaK-mqiyq_K4FF$>s5USCY2&u5`jyoz`(5j=Qt%$0Hnkqr_l z3!Hioo9~X)mNz5z+z2Ld1naQ5P580T{Wwo({2B_UnP_9jMrr*|#OIj#vXWy?tob*H z^j@O5rIWh$m8IaEOabpWjF``2mU|aYUubGTO4tU1zJQ??H{&9^eo;VrvO&zf{>mx^7vOi+tnC&p~dIPT`#;%D` z*&P{JZKkMPN6Bfa%#KF)Nf&=jir*IEql>K88hG#;v|DS+B+zJN((xZd^(f+5vKA*O z+ZR=AXg7F@9sGZ0TR3gsB4hh%+Ux_G}v?eijU>1K8GneU6ieQ%!r4P&YFK2(zkW=#9I>VRnE@4)5%MMApt!U z*K$z;3dFZgCo$<-Hem~d|BFPIcLyDQRGjR4@o-y|Y8?&A@71_0+*P;xW=s2jHqA7A}#+|eV zNQtxiq+%PX8U=Q6D(Dte)=-}e<^+vX+BH34S7gGjKUTBEqYhF zBXgZwi>CAoQaFBq9ffdstl1{iyNsNEQJmIkI3->i5xhhZSj_NWB9^=2&~I>qSRpHX ztED;kBdG*5&qq=iYX6axz(GZKf$|K|O+OfGx}(wcJr>08dXtz1EUGQ-`0l~d zGSup@-iO0u;`OBs;`p}FVw<-+k^FV zUairaGWs4ipT+(jR#7>h%jU($0;j6db5-hjRb7y`BF5s{A)uvc+M_+Dl{Iw6Ecr?_ iIt`4OhWfEl?QDOdU(V5-rTIh~q(1?tbfULbKL7yG->>=r literal 2363 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 From 4bdfb1085340d6cac7e5c8d8af982e212fa44d05 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Thu, 15 Aug 2024 13:38:30 +0800 Subject: [PATCH 51/70] update test case --- test/prefer-global-this.mjs | 2 + test/snapshots/prefer-global-this.mjs.md | 42 +++++++++++++++++++++ test/snapshots/prefer-global-this.mjs.snap | Bin 2416 -> 2501 bytes 3 files changed, 44 insertions(+) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index f3c4f65d61..e2c4b72be4 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -161,6 +161,8 @@ test.snapshot({ 'window.addEventListener("play", () => {})', 'window.onplay = function () {}', 'function greet({ name = window.foo }) {}', + '({ foo: window.foo } = {})', + '[window.foo] = []', ], }); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 68b78b6658..f9209d8227 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -1129,3 +1129,45 @@ Generated by [AVA](https://avajs.dev). > 1 | function greet({ name = window.foo }) {}␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` + +## invalid(49): ({ foo: window.foo } = {}) + +> Input + + `␊ + 1 | ({ foo: window.foo } = {})␊ + ` + +> Output + + `␊ + 1 | ({ foo: globalThis.foo } = {})␊ + ` + +> Error 1/1 + + `␊ + > 1 | ({ foo: window.foo } = {})␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ` + +## invalid(50): [window.foo] = [] + +> Input + + `␊ + 1 | [window.foo] = []␊ + ` + +> Output + + `␊ + 1 | [globalThis.foo] = []␊ + ` + +> Error 1/1 + + `␊ + > 1 | [window.foo] = []␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index f2f018080fcabca8cebe57a11d7db21beb9b318b..fb6135b3500d1a7cb8cd706225ddf0ebe179b280 100644 GIT binary patch literal 2501 zcmV;$2|D&cRzVJ=}M*WJR=I zjMZ1ts~?L900000000BMTWyaV#SuP;qR6Kx$_o&1j42<+-t``Px3jy(-sAQnz?MOf z7_czX0lC@T-n)Te<~%$1rn^-X1&EX{d<6+1!6&5rhWvy4sHk^)db*~oXL|O=>?i9y z&r?-Tb@fY4&ky5)9}Yj8eB=DcVlVbtM!?IBLDzr@X724_aioD5$vRdI}jeGf7xjY1Kyn|3L|K(wM4Z0NwiMA2NULx z^;j<=H-0UA=g(Fa>0Jc6B_f@fNaM_jl0RvVQD(GV@4=B5jKU+^jLx5a%o!C%EHgTP z+8pg+5^YCD+Z>0X9x)w3ilCytiZIV;Q7bqc`F#X@4Mjc!RTTYE5`9-jzda7akM;1c zAdmil!kCh^V2-Ltf#c^A32vqmtc=5Og%IIIhLG21K(1HgHM|-Y#Qr@-XdZYr9}g zF{)Ng6?OBn)P-+0#|ObM_QK!>?6RO%hf_H5m_JHVGS!uO137(DM6B^F12{9kRla3_ zHk`qfQt}?+?OF0F3S(}p^cf-#jO2aV>BTaD9nv%5$V~7(uRA#jhSDXO4)@6Q;+%B6 zi6Yw&k-%*?B=`=M`nw0er&l!N865RM2yQ zj--@cMcB*44n)J-tiOcus^-^JAHG57{K-OJP9Gg zbX%%4a3e6cbn;YEk!4kyV+&TK5hC~isf3KL~>N>wxI_>Z>W*M zRG9M*%Xg#}{Gc%mgGtQyXs`*VJU!~!W0e<){KLSFR>i-2#IXHRg!2f6GZac7J7R2I z$eI&*ypXlJ4A9|!$Htcdx~4Hs4@0vP`1FGvQT~r|1{FrvSQtO49zFT(66sRks0+{k zg@vkOF*W75X_xWel-It|lf~k)_TQ2I{|EX1T{-_vO7;z&q*0X&j0mB<)=o-yAWOHc zt|$}s=zs-7_JB>|+0x>(7>-xrWCM<26KW^?D7wB1C(wXyQo{9(S?r+ZzGDAv_poO z1}Exoi055&)}T15I&w6mcD!{FySvg@I`^0b>>#hNiRklLC>3uZo*M)YUL13!+(%>s zA!UJ6k7M)QmfG@W#GxC(B#vMccJ>HAj<_FJ2#sGw;WULdc5IZ^e@1+cnJ+6j=ER!+ z9g#i~np--lYhPIkF3S|~j>CxgEM~dy!s!>98jupUfuPT0sKuLc`Z%qdMsl57q64WA z?>RIYrZeuOY^c ziBZ`d8CY$ms9ZLIsA5BVgQwWR|7W&^)Al7YcBH1wKA;8OoaZLb5zc*&w%1=TozpwhuM)4Fwd7*s z@tPcRPBP@?XHYL@pF=oSd@Nt}IZWboQMT$aBOXRNYyQiSzOAF@-jZOia(3SBc3u(; z3Fx7?R*Mo)Aii}viAmS830oli&m_8hchKfX#mSKu5BHK%t-~oHH2v;CN7}zTNU%st zTErbh@LqBqRyPh6ztNWOQQKWbr#L!bd^`@_NwOpD!60JpXJprgUW+nhNykCuOqwDW z=G>w+KuVn5Cl%XB)hMuoQ$e?&vWEI(Fz0BT(yr+VyD1ZPGe2R?S!2Y#VoocoT^5fKs4p|Vt?M-49u&B1O z@4F`}t5B=MW*<(c#Py{uKatcN^IIGfLc7r;~7iwX^ z?ZIX`uh!^I8T}qMpT+(?tfF#0m(9h;0;j6dvn%zyr7p<35o2-f6wuN%>(NeWWeuG% zOTH3~P6K16p*}ULo$XKb%Q>2}G*_}gx-Rp<4;eM>njcL0MI_fV zBw3L$5!Ts5Oxr@|Ja?+@&B=G#U4Ay%PECFco3KrM+e@!M8qj`wvyBBqaGRrwZdz!x PxH$g@&mSuFzCi#0R_NCb literal 2416 zcmV-$36J(cRzVEma0i4CLdArzn|0Q^v+Izo@%jV=1;k5$ zh(scQXLoz;fnmm(9ow;N3!UybB);$!By`g835nmpKj259-kt90ny#MdSx?wcku%Rz zRZn&GOZCkE#{)kcel_{A^$Ux=*k_R!?76--swA;H-I;8M@#NpXj7Dzk z-Z}g5!lMiP_s}B?Pd@bcB0w9ClBXA$?+%#H-VSzl!(lyDQmz4R}e&BTCrJ&M8z+AHlO+8q(CQ}4lq`C~oS zGsum{65si=l|}j%0$oiaotjAF%!!geX^v55v{UcFz88$becO!Ao_@d?O^jG(boR74 z+C33%S4P_$hoK%Z9YKnqqP~DI&uCFAI2`#+1biJuJ_S`2{l18PRYw2mI1E42!#|Ha z`a24L3ZdeE8G)YF;#YxKfDaM!4J5z}RgnVspA!;XNhMeshv5<-!b`}jr?Ch#5GBJa z2=<&V1A<~9K1SHJ)o7wV zjEOr4`c66~QiIB%s6dSuq#6#ICSe`gPDfXSjxCF$RJnwZXUXXjp>3)~GhF>BNjHur zO>(Qns7GP7n6=2QmTGl)Uh2TNl;PmZrVH!FdZD+77)5DOL%1^;TtUs;Md0@nH8Muk zs;Q!GE=yhbW^=q73}Y`0F2NQHYIQh-1CRM5k&>bJ_b2+)Be zIHr`mfp~kCyo$n@8!LT;$O9vJpLTk_3}A=!OgJ(Ve9!An4uYX{Nv6ZycfB|#9dDz^ z){@9*GO3+PnwOLJ5cx(Ka?8a03t5=tTjHiMeGfv#*l!{^Ds|h?gP=Fm$Y3hW z$%o~8QVV|27>2YJfBR{Hbg6IDh3Eg& zTvaijnsVH9%J^@}Yv1U}d~sR(?@0fDL;n9<&VQ4VeS;@yR3!r=Lg=h?MClG>>2}l= zWy0?5vS7$=u}M5#T6`A6{be{Z7stAG+PaK-mqiyq_K4FF$>s5USCY2&u5`jyoz`(5j=Qt%$0Hnkqr_l z3!Hioo9~X)mNz5z+z2Ld1naQ5P580T{Wwo({2B_UnP_9jMrr*|#OIj#vXWy?tob*H z^j@O5rIWh$m8IaEOabpWjF``2mU|aYUubGTO4tU1zJQ??H{&9^eo;VrvO&zf{>mx^7vOi+tnC&p~dIPT`#;%D` z*&P{JZKkMPN6Bfa%#KF)Nf&=jir*IEql>K88hG#;v|DS+B+zJN((xZd^(f+5vKA*O z+ZR=AXg7F@9sGZ0TR3gsB4hh%+Ux_G}v?eijU>1K8GneU6ieQ%!r4P&YFK2(zkW=#9I>VRnE@4)5%MMApt!U z*K$z;3dFZgCo$<-Hem~d|BFPIcLyDQRGjR4@o-y|Y8?&A@71_0+*P;xW=s2jHqA7A}#+|eV zNQtxiq+%PX8U=Q6D(Dte)=-}e<^+vX+BH34S7gGjKUTBEqYhF zBXgZwi>CAoQaFBq9ffdstl1{iyNsNEQJmIkI3->i5xhhZSj_NWB9^=2&~I>qSRpHX ztED;kBdG*5&qq=iYX6axz(GZKf$|K|O+OfGx}(wcJr>08dXtz1EUGQ-`0l~d zGSup@-iO0u;`OBs;`p}FVw<-+k^FV zUairaGWs4ipT+(jR#7>h%jU($0;j6db5-hjRb7y`BF5s{A)uvc+M_+Dl{Iw6Ecr?_ iIt`4OhWfEl?QDOdU(V5-rTIh~q(1?tbfULbKL7yG->>=r From d00d8707404d35ea268f23534697fa294eb37112 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Mon, 19 Aug 2024 09:13:50 +0800 Subject: [PATCH 52/70] add test --- test/prefer-global-this.mjs | 1 + test/snapshots/prefer-global-this.mjs.md | 111 ++++++++++++--------- test/snapshots/prefer-global-this.mjs.snap | Bin 2501 -> 2523 bytes 3 files changed, 67 insertions(+), 45 deletions(-) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index e2c4b72be4..0fb856c3b6 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -61,6 +61,7 @@ test.snapshot({ 'window', 'window.foo', 'window[foo]', + 'window[title]', 'window["foo"]', 'window.foo()', 'window > 10', diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index f9209d8227..e6d6d6c916 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -109,7 +109,28 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(6): window["foo"] +## invalid(6): window[title] + +> Input + + `␊ + 1 | window[title]␊ + ` + +> Output + + `␊ + 1 | globalThis[title]␊ + ` + +> Error 1/1 + + `␊ + > 1 | window[title]␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ` + +## invalid(7): window["foo"] > Input @@ -130,7 +151,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(7): window.foo() +## invalid(8): window.foo() > Input @@ -151,7 +172,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(8): window > 10 +## invalid(9): window > 10 > Input @@ -172,7 +193,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(9): 10 > window +## invalid(10): 10 > window > Input @@ -193,7 +214,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(10): window ?? 10 +## invalid(11): window ?? 10 > Input @@ -214,7 +235,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(11): 10 ?? window +## invalid(12): 10 ?? window > Input @@ -235,7 +256,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(12): window.foo = 123 +## invalid(13): window.foo = 123 > Input @@ -256,7 +277,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(13): window = 123 +## invalid(14): window = 123 > Input @@ -277,7 +298,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(14): obj.a = window +## invalid(15): obj.a = window > Input @@ -298,7 +319,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(15): function* gen() { yield window } +## invalid(16): function* gen() { yield window } > Input @@ -325,7 +346,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(16): async function gen() { await window } +## invalid(17): async function gen() { await window } > Input @@ -352,7 +373,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(17): window ? foo : bar +## invalid(18): window ? foo : bar > Input @@ -373,7 +394,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(18): foo ? window : bar +## invalid(19): foo ? window : bar > Input @@ -394,7 +415,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(19): foo ? bar : window +## invalid(20): foo ? bar : window > Input @@ -415,7 +436,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(20): function foo() { return window } +## invalid(21): function foo() { return window } > Input @@ -442,7 +463,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(21): new window() +## invalid(22): new window() > Input @@ -463,7 +484,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(22): const obj = { foo: window.foo, bar: window.bar, window: window } +## invalid(23): const obj = { foo: window.foo, bar: window.bar, window: window } > Input @@ -518,7 +539,7 @@ Generated by [AVA](https://avajs.dev). 5 | }␊ ` -## invalid(23): function sequenceTest() { let x, y; x = (y = 10, y + 5, window); console.log(x, y); } +## invalid(24): function sequenceTest() { let x, y; x = (y = 10, y + 5, window); console.log(x, y); } > Input @@ -551,7 +572,7 @@ Generated by [AVA](https://avajs.dev). 5 | }␊ ` -## invalid(24): window`Hello ${42} World` +## invalid(25): window`Hello ${42} World` > Input @@ -572,7 +593,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(25): tag`Hello ${window.foo} World` +## invalid(26): tag`Hello ${window.foo} World` > Input @@ -593,7 +614,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(26): var str = `hello ${window.foo} world!` +## invalid(27): var str = `hello ${window.foo} world!` > Input @@ -614,7 +635,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(27): delete window.foo +## invalid(28): delete window.foo > Input @@ -635,7 +656,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(28): ++window +## invalid(29): ++window > Input @@ -656,7 +677,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(29): ++window.foo +## invalid(30): ++window.foo > Input @@ -677,7 +698,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(30): for (var attr in window) { } +## invalid(31): for (var attr in window) { } > Input @@ -704,7 +725,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(31): for (window.foo = 0; i < 10; window.foo++) { } +## invalid(32): for (window.foo = 0; i < 10; window.foo++) { } > Input @@ -740,7 +761,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(32): for (const item of window.foo) { } +## invalid(33): for (const item of window.foo) { } > Input @@ -764,7 +785,7 @@ Generated by [AVA](https://avajs.dev). 2 | }␊ ` -## invalid(33): for (const item of window) { } +## invalid(34): for (const item of window) { } > Input @@ -788,7 +809,7 @@ Generated by [AVA](https://avajs.dev). 2 | }␊ ` -## invalid(34): switch (window) {} +## invalid(35): switch (window) {} > Input @@ -809,7 +830,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(35): switch (true) { case window: break; } +## invalid(36): switch (true) { case window: break; } > Input @@ -839,7 +860,7 @@ Generated by [AVA](https://avajs.dev). 4 | }␊ ` -## invalid(36): switch (true) { case window.foo: break; } +## invalid(37): switch (true) { case window.foo: break; } > Input @@ -869,7 +890,7 @@ Generated by [AVA](https://avajs.dev). 4 | }␊ ` -## invalid(37): while (window) { } +## invalid(38): while (window) { } > Input @@ -893,7 +914,7 @@ Generated by [AVA](https://avajs.dev). 2 | }␊ ` -## invalid(38): do {} while (window) {} +## invalid(39): do {} while (window) {} > Input @@ -914,7 +935,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(39): if (window) {} +## invalid(40): if (window) {} > Input @@ -935,7 +956,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(40): throw window +## invalid(41): throw window > Input @@ -956,7 +977,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(41): var foo = window +## invalid(42): var foo = window > Input @@ -977,7 +998,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(42): function foo (name = window) { } +## invalid(43): function foo (name = window) { } > Input @@ -1004,7 +1025,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(43): self.innerWidth +## invalid(44): self.innerWidth > Input @@ -1025,7 +1046,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^ Prefer \`globalThis\` over \`self\`.␊ ` -## invalid(44): self.innerHeight +## invalid(45): self.innerHeight > Input @@ -1046,7 +1067,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^ Prefer \`globalThis\` over \`self\`.␊ ` -## invalid(45): window.crypto +## invalid(46): window.crypto > Input @@ -1067,7 +1088,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(46): window.addEventListener("play", () => {}) +## invalid(47): window.addEventListener("play", () => {}) > Input @@ -1088,7 +1109,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(47): window.onplay = function () {} +## invalid(48): window.onplay = function () {} > Input @@ -1109,7 +1130,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(48): function greet({ name = window.foo }) {} +## invalid(49): function greet({ name = window.foo }) {} > Input @@ -1130,7 +1151,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(49): ({ foo: window.foo } = {}) +## invalid(50): ({ foo: window.foo } = {}) > Input @@ -1151,7 +1172,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(50): [window.foo] = [] +## invalid(51): [window.foo] = [] > Input diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index fb6135b3500d1a7cb8cd706225ddf0ebe179b280..154b900bb51a3f922f50b2a299929ee8fc88dbfd 100644 GIT binary patch literal 2523 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 literal 2501 zcmV;$2|D&cRzVJ=}M*WJR=I zjMZ1ts~?L900000000BMTWyaV#SuP;qR6Kx$_o&1j42<+-t``Px3jy(-sAQnz?MOf z7_czX0lC@T-n)Te<~%$1rn^-X1&EX{d<6+1!6&5rhWvy4sHk^)db*~oXL|O=>?i9y z&r?-Tb@fY4&ky5)9}Yj8eB=DcVlVbtM!?IBLDzr@X724_aioD5$vRdI}jeGf7xjY1Kyn|3L|K(wM4Z0NwiMA2NULx z^;j<=H-0UA=g(Fa>0Jc6B_f@fNaM_jl0RvVQD(GV@4=B5jKU+^jLx5a%o!C%EHgTP z+8pg+5^YCD+Z>0X9x)w3ilCytiZIV;Q7bqc`F#X@4Mjc!RTTYE5`9-jzda7akM;1c zAdmil!kCh^V2-Ltf#c^A32vqmtc=5Og%IIIhLG21K(1HgHM|-Y#Qr@-XdZYr9}g zF{)Ng6?OBn)P-+0#|ObM_QK!>?6RO%hf_H5m_JHVGS!uO137(DM6B^F12{9kRla3_ zHk`qfQt}?+?OF0F3S(}p^cf-#jO2aV>BTaD9nv%5$V~7(uRA#jhSDXO4)@6Q;+%B6 zi6Yw&k-%*?B=`=M`nw0er&l!N865RM2yQ zj--@cMcB*44n)J-tiOcus^-^JAHG57{K-OJP9Gg zbX%%4a3e6cbn;YEk!4kyV+&TK5hC~isf3KL~>N>wxI_>Z>W*M zRG9M*%Xg#}{Gc%mgGtQyXs`*VJU!~!W0e<){KLSFR>i-2#IXHRg!2f6GZac7J7R2I z$eI&*ypXlJ4A9|!$Htcdx~4Hs4@0vP`1FGvQT~r|1{FrvSQtO49zFT(66sRks0+{k zg@vkOF*W75X_xWel-It|lf~k)_TQ2I{|EX1T{-_vO7;z&q*0X&j0mB<)=o-yAWOHc zt|$}s=zs-7_JB>|+0x>(7>-xrWCM<26KW^?D7wB1C(wXyQo{9(S?r+ZzGDAv_poO z1}Exoi055&)}T15I&w6mcD!{FySvg@I`^0b>>#hNiRklLC>3uZo*M)YUL13!+(%>s zA!UJ6k7M)QmfG@W#GxC(B#vMccJ>HAj<_FJ2#sGw;WULdc5IZ^e@1+cnJ+6j=ER!+ z9g#i~np--lYhPIkF3S|~j>CxgEM~dy!s!>98jupUfuPT0sKuLc`Z%qdMsl57q64WA z?>RIYrZeuOY^c ziBZ`d8CY$ms9ZLIsA5BVgQwWR|7W&^)Al7YcBH1wKA;8OoaZLb5zc*&w%1=TozpwhuM)4Fwd7*s z@tPcRPBP@?XHYL@pF=oSd@Nt}IZWboQMT$aBOXRNYyQiSzOAF@-jZOia(3SBc3u(; z3Fx7?R*Mo)Aii}viAmS830oli&m_8hchKfX#mSKu5BHK%t-~oHH2v;CN7}zTNU%st zTErbh@LqBqRyPh6ztNWOQQKWbr#L!bd^`@_NwOpD!60JpXJprgUW+nhNykCuOqwDW z=G>w+KuVn5Cl%XB)hMuoQ$e?&vWEI(Fz0BT(yr+VyD1ZPGe2R?S!2Y#VoocoT^5fKs4p|Vt?M-49u&B1O z@4F`}t5B=MW*<(c#Py{uKatcN^IIGfLc7r;~7iwX^ z?ZIX`uh!^I8T}qMpT+(?tfF#0m(9h;0;j6dvn%zyr7p<35o2-f6wuN%>(NeWWeuG% zOTH3~P6K16p*}ULo$XKb%Q>2}G*_}gx-Rp<4;eM>njcL0MI_fV zBw3L$5!Ts5Oxr@|Ja?+@&B=G#U4Ay%PECFco3KrM+e@!M8qj`wvyBBqaGRrwZdz!x PxH$g@&mSuFzCi#0R_NCb From 45dd21cca8c31eaf6706f71eebe10084b52373c0 Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 19 Aug 2024 23:44:09 +0800 Subject: [PATCH 53/70] Simplify --- rules/prefer-global-this.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 0ecddb00ad..54a8805de7 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -144,9 +144,9 @@ function report(context, node, value) { Handle nodes and check if they should be reported. @param {import('eslint').Rule.RuleContext} context -@param {import('estree').Node | Array} nodes +@param {import('estree').Node} nodes */ -function handleNodes(context, nodes) { +function handleNode(context, nodes) { if (!Array.isArray(nodes)) { nodes = [nodes]; } @@ -214,11 +214,11 @@ const create = context => { ...tracker.createListeners(context), /** @param {import('estree').AssignmentExpression} node */ AssignmentExpression(node) { - handleNodes(context, [node.left]); + return handleNode(context, node.left); }, /** @param {import('estree').UpdateExpression} node */ UpdateExpression(node) { - handleNodes(context, node.argument); + return handleNode(context, node.argument); }, }; }; From 06802064badec81d3df9cf57dc27624cc03badc4 Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 19 Aug 2024 23:45:36 +0800 Subject: [PATCH 54/70] Simplify --- rules/prefer-global-this.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 54a8805de7..7e47459f30 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -200,13 +200,14 @@ const create = context => { handle(reference) { const {node} = reference; - if (node.type === 'Identifier') { - if (isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent)) { - return; - } - - report(context, node, node.name); + if (node.type !== 'Identifier' + || isWindowSpecificAPI(node.parent) + || isWebWorkerSpecificAPI(node.parent) + ) { + return } + + report(context, node, node.name); }, }); From 56aed7e5d019744cad11aa67f49ca459da196909 Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 19 Aug 2024 23:46:35 +0800 Subject: [PATCH 55/70] Simplify --- rules/prefer-global-this.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 7e47459f30..c184f8a89b 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -128,14 +128,13 @@ Report the node with a message. @param {import('eslint').Rule.RuleContext} context @param {import('estree').Node} node -@param {string} value */ -function report(context, node, value) { +function report(context, node) { const fix = (/** @type {import('eslint').Rule.RuleFixer} fixer */ fixer) => fixer.replaceText(node, 'globalThis'); context.report({ node, messageId: MESSAGE_ID_ERROR, - data: {value}, + data: {value: node.name}, fix, }); } @@ -153,7 +152,7 @@ function handleNode(context, nodes) { for (const node of nodes) { if (node.type === 'Identifier' && globalIdentifier.has(node.name) && !isShadowed(context.sourceCode.getScope(node), node)) { - report(context, node, node.name); + report(context, node); } } } @@ -207,7 +206,7 @@ const create = context => { return } - report(context, node, node.name); + report(context, node); }, }); From 13d9d89b2d8b9833082536292a0726d222226ac2 Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 19 Aug 2024 23:49:10 +0800 Subject: [PATCH 56/70] Simplify logic --- rules/prefer-global-this.js | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index c184f8a89b..883bdc940c 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -126,34 +126,26 @@ const webWorkerSpecificAPIs = new Set([ /** Report the node with a message. -@param {import('eslint').Rule.RuleContext} context @param {import('estree').Node} node */ -function report(context, node) { - const fix = (/** @type {import('eslint').Rule.RuleFixer} fixer */ fixer) => fixer.replaceText(node, 'globalThis'); - context.report({ +function getProblem(node) { + return { node, messageId: MESSAGE_ID_ERROR, data: {value: node.name}, - fix, - }); + fix: (/** @type {import('eslint').Rule.RuleFixer} fixer */ fixer) => fixer.replaceText(node, 'globalThis'), + }; } /** Handle nodes and check if they should be reported. @param {import('eslint').Rule.RuleContext} context -@param {import('estree').Node} nodes +@param {import('estree').Node} node */ -function handleNode(context, nodes) { - if (!Array.isArray(nodes)) { - nodes = [nodes]; - } - - for (const node of nodes) { - if (node.type === 'Identifier' && globalIdentifier.has(node.name) && !isShadowed(context.sourceCode.getScope(node), node)) { - report(context, node); - } +function handleNode(context, node) { + if (node.type === 'Identifier' && globalIdentifier.has(node.name) && !isShadowed(context.sourceCode.getScope(node), node)) { + return getProblem(node); } } @@ -206,7 +198,7 @@ const create = context => { return } - report(context, node); + return getProblem(node); }, }); From 29d89e54c6dcc28b2a79892dd70ecd97b1d48ef6 Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 20 Aug 2024 00:20:40 +0800 Subject: [PATCH 57/70] Add tests --- test/prefer-global-this.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 0fb856c3b6..ec8c76d008 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -54,6 +54,8 @@ test.snapshot({ const {window} = jsdom() window.jQuery = jQuery; `, + '({ foo: window.name } = {})', + '[window.name] = []', ], invalid: [ 'global', From 1575cd884bbb2002d5879bef98d5858966e53d63 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 20 Aug 2024 15:00:24 +0800 Subject: [PATCH 58/70] fix: lint --- rules/prefer-global-this.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 883bdc940c..1a7e667a0b 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -195,7 +195,7 @@ const create = context => { || isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent) ) { - return + return; } return getProblem(node); From 75472c5350d4862edf727d35a46d618f0e086c7d Mon Sep 17 00:00:00 2001 From: Axetroy Date: Thu, 22 Aug 2024 11:14:25 +0800 Subject: [PATCH 59/70] add test case for `foo[window]` and `foo[window.foo]` --- test/prefer-global-this.mjs | 2 + test/snapshots/prefer-global-this.mjs.md | 42 +++++++++++++++++++++ test/snapshots/prefer-global-this.mjs.snap | Bin 2523 -> 2599 bytes 3 files changed, 44 insertions(+) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index ec8c76d008..d3b7be8fce 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -166,6 +166,8 @@ test.snapshot({ 'function greet({ name = window.foo }) {}', '({ foo: window.foo } = {})', '[window.foo] = []', + 'foo[window]', + 'foo[window.foo]', ], }); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index e6d6d6c916..05bd25303f 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -1192,3 +1192,45 @@ Generated by [AVA](https://avajs.dev). > 1 | [window.foo] = []␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` + +## invalid(52): foo[window] + +> Input + + `␊ + 1 | foo[window]␊ + ` + +> Output + + `␊ + 1 | foo[globalThis]␊ + ` + +> Error 1/1 + + `␊ + > 1 | foo[window]␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ` + +## invalid(53): foo[window.foo] + +> Input + + `␊ + 1 | foo[window.foo]␊ + ` + +> Output + + `␊ + 1 | foo[globalThis.foo]␊ + ` + +> Error 1/1 + + `␊ + > 1 | foo[window.foo]␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 154b900bb51a3f922f50b2a299929ee8fc88dbfd..20450719c8ca0602ae6d2a44b43189625d710b58 100644 GIT binary patch literal 2599 zcmV+?3fT2QRzV@b0@WSeE@d*sqd}>wBbTLz0N#m#60%4e{>v)=K($c1N8iZLw6=H(_bA& zDd-&p8mga6x$zz0JAbyaNZ&%BJ0jABi8RifDEX7-7-dGg^#Po^{v+tENwhr~ZF3p~dc<@DDT0dnI>P)|i(0|q$nPWI>nQRCsG{gklj!?0`n_ooe5{9m z4SDoK6#fE2#s3ll{X~mj1!4i-L&!If05Pf}1s*?}NN_uqVDTG5gcp%lPh$~c5GBJ+ z1bbGO0YR}4zed=*SO|fuT#8pxDK@4-uu)cu7_^iW2wFl4fvZZ2XA&vypk<*}*Ok~n zZv9AG7;1G&h#Ls?47oH&B-Y`51btIm9BTE-mxouS3NVCrtK9OifGo2-s6hMWAx2d` z5ZbN!0NO1W8uvt60|jEQ!2(pUJAQzW_k;$jxmbh6Plby^yPXb(-Cc4tSDMOr!>tK~aGk&r3DBXrY81Xm`50 zB6Mt79Hq)FguFs7mRwa+Nq>@Ie8b6@0KCAOw1pUg;~CZ zA?^N?$<7NhJ9m^*2k-@Z03#>VQ$eo*Kz@zBl5sRJ~TLuvQXXPCl8Sw zUTXO4R9Lj{LZ}$~LnKF~ZX3D~^nn@~Oodr}SiUQ@;DyFG@MjS}qrncG^Yo~-$0na7 z@;^pSxGDZUAcpN1BAiDkoUu>>*%4#wQr4WvuRKV}cuELvUW6eJydH@995MZ4XGV(T|~}-G?uPC zW&wN1>l-5ad=^T@JBa5N!Gkx)Tq%zb*+@uP;M9{ie0Qa`ycu!ggfNRj*n#~+!jDt# z$2CIZ*HAc3p^Y6IrS(q{U&qXsl^k=P}gcngCr+>!y)hD@$}N72-XIM#EG?Uq#-1PehkIPw7DyF^xt+y-eSh zkcN`zE9~lbTT0~gurS4vKO*RYOjW=*7#<+#TNxG5I9OeYx>RD(B?v;O@u}-XQ3!5Q z8S_IOaWoquM_aN#V&aHT7kw;WcQtwv|Po(a5CZPlnl}h-b-KoS+mb`Bn+&mR+8*TX>wR>C9DGHAnACF^a zmYhfjFbbLT8QHa=_o570(s58Zlcva}m|L_4NQtxOq+%PX8U=Q6D(Dte*3gg)W`)Kn z?V6sj+cIIVxf2XT-BHqp<~P9?C*u9 z$O2{P^O9ybJB=#5XVL3s?pZ+1cRpv*wqY$dR6n^q#f5tI)3O}avfY%wAnLQ^cwgkO zvDB@)t8zsqq$fV^Yr4MA!iVl8I@I;2FYaex_Dx^qsG`AbzJ16VhSfg=R3>pBDRPgw z2ZxdEB+lZNxp+t5ZLTzHrmIlpvQ#DgVyrn1&yFIZ3!L|vlmIRBnG}ZFei<{^P_j%S;Tx6);5kj=WJsWYIWEd!ug!IzO;*+ZeyK_2`LTVK$Lx5 zLu*>BZ-96mtgi)URocsLP*3?rE%3QL*h$yb8ht3E-^1p!*uRHWRL<8}dQOSX4U)v^6byv~yZnLubsAuSBEMz?f;M&y8wl`xC=*j^=F5l^l?6%5Rf- zkx|pG`N5oDexeo=y3R5%n3j(|BDt9%$%>4Lu+A=G+7mkGxl?s-PQKIb^V(!DHTf~@ zz#j2+FTMY0K>Op(9u^G2ZAum0w9sgEapV`C{rGKKAZ%HG1g}6SLFj`b2c^!^Qv3!X zf0o_@m*%Q0VCDI@-$gn!=|2cy4oiVidejl{IZ}_N@ec$17NLKkY0^~wIKXPU{2yOO Jl6~t$006!x2~Pk3 literal 2523 zcmV<12_*JGRzVqef( z3}iMa=pTy+00000000BMTWxP6)fEn{Dzs5m^^F#`%W^g>yY@Ob_Sjw)hd33mXhF~} zbj2bCXvX$+GBC_!$CEcD7OGl`#23C&sj5^yA@Ljd2mMjiweQ@yXYRQ(cbr-BDN5#f z&N^MSL)Z7FfqO9B598_Iza5X= z*!|$jPgkB?;XhCOY~@!^{9+ZL4d>$NRpz@x=Ce10gTq)n59s+{qvs#&dsBg#{P{3W zL2o0_V0EAx0RT9MkLN#dKVlOW!EQ>p3*k}vm))i?;N6X)FoO0*TSR-1MC;W1FlGKk zkM%NgQX`DGx@+ZwP%8YjEeK_`lad>Q-(Z$n`IitdeWkwfI zo1;BSqV39Po0BlqBc>xr5meOI5$1PV)Cvwqejfo}MUl@z6-9rXMBkIq?@Yq*BR%|U z$fMt&@aGUJ{udDF_gefa5DV}wLcWFsSfDCW;N+P^g4?MC^ZyVcJdeD33X8A+Q8L^_ zuxE4`5EKjX7lgfwg%G&PrFbcoVr>$JYh|TafR>U1K}$#>a8*h1bRxwav@F!>x)N*1 zt>0=3L#<8;aRZ^ACYJ_@#5%l(ps#C-L#kY$z!6==UaEKrpX zgm$amhjt4F#yyeNK!Mn6Fb5Uvj_)JnJ)wbWZlS^ar^3ad-A)I?_BJ^h@}|TBv&@u0 zNc$-vV3jYDZD%ncwzrKVg4RLB*z2%B6^w}w5cI8dOr!>tK~aGk&q_5qXrY8HXgeKU z5jwUkj#A|oLS7*kOoXrQ|)t+qdLZ6vo_G>2pLL7|92;)5~Q5 zJEUjAk(uD9UUzyLjHF949qzH~#X0GC6GgTuBBRNqb}DIJPToP}+hxct6Z1D@VVZAY zK)e5Vvh$qG&K>2{0er#k!_bZNRM2aIj--@cN7$>x2}Hx&?7xKZs@B(3AAUsV{K-aN zP9GgnjS<27NF`(( z&$^0tCa10JOfau2;S3@cA4b8_J5$0V*D1ue{LWW zOO1dX3ybz$2o+<0h~%i$Z9^A=K2RfrsW2BGmhVU{c%d;0gK5mqXs`umJUwddvCb!n z{KL?V*2V9AV%UBm!g++k83`qj9Wk~pWzC5^Udmcs1?cj>W8W52 zl>brApo!5lPK@tVkACv671E`FQ5T;7OH0j)<qvtpJ*zbWLNa8@kB%ELn2VhDk^4~!eFK9)EnFc57uZZVeRBKQiRh1kKsU2@!#O|InmaaW! z0lUcS8zTCA7D~lCi02l;gEz-qDGw0YP)J$e)Z;jOcciww8FA!BFpVSFg57<>k7Mq~ zHA3T8P&iGYjU5}M^&b(RW9G|BjybXBpCi&oLUT(eb?qxl!Bv?8-fK$p|HX(ZQ$B|4M}@t#AYVXC38BJX}FqD!8q^q`BFMx&r!rf*9~ zLrL@%cJ(_gC31RLm}1Ev5p+SODqtK84-oW?j0$KRTwIB|RASyG2qUQRsq4mZ1YS}Z z^FtkRG#emCTe3f5;#iz8@_GZWBF3(XQ8^tMSZ$W5Tt~@esmzH+_emFjQ;P2-;-eQ? ztxfRY6==6Ml|`V@$fV;RhS{TtXUSTepln}Mv7x=eQ|#dXnQh^;eSwS}t7)?jXo)xH zxyf^cbN@ld>#tWX=$+}O60e;NCmC`Za>#X(A-AYOy_kIl;Y9JV{H)Jm64gc7S&td< zFw$A`Uxo~99lh|81bdZp^6qr=l3++cAH}s^lz;;9tMOxA#?jnNslDomWaj5u>wtSD;xvl6FM~94$$B{ct zPNaPpM$G+`?Ap+KQHCt(IH;USQ{>WuTeJp9iL>XVVjHO%1$J;M=oVDg(0~l)0*zDJ zH9cXsWx`&{Pgrx_STrZCyr2qiiNw)|2)o2t*uu%9yL83LOAP%82~1a}`MdFb&u7XE zr!v(#R~rkV)-yB`VDRnJ7k5oy1Kj$_9pqd(YLxV%Klat$62UE-^9om zg$iF#%HBYiSH$st6ee#%ZF>VM#=bYOKrMAI6d8oab1$^(h(_k3sxc`-$Cky}-wREV z1eJ+SU*xc{ z)UCR!az!SjD?aXPdO^UVhu%2e*Y&3_?q^{3O<(1xqQPyxeaISyi+>2HOyV9=hc!IPWtl0b1rWDGas$Oe(=aMehP- z4be?M8Ed-Z@!ca9#BY1km<24VtsVI8>DoHf>aaC{vl(%HX&X7+#yS-fQX0O7D0{kw z*0fmP5b?TLUklEvw3pqWuJVmq7;t;Am9DEb`cOu{hs|fPe-EpuoX=%*@v*?Es`Tth zJzrKgG!EgwBZax+7c6&Vv@ojt^~BXrJlr|RCEe5c*xwaHFu@*~)S l9pdX=djHXY_Q#tYEEs~@lq$Muq0#c<{2w20JQmAB000%->fitX From 2f83ffe4da44df717b322244b0ac6b144f4c34d8 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Sat, 24 Aug 2024 20:04:17 +0800 Subject: [PATCH 60/70] update test --- rules/prefer-global-this.js | 10 ++ test/prefer-global-this.mjs | 6 +- test/snapshots/prefer-global-this.mjs.md | 155 ++++++--------------- test/snapshots/prefer-global-this.mjs.snap | Bin 2599 -> 2520 bytes 4 files changed, 59 insertions(+), 112 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 1a7e667a0b..d95bc560eb 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -176,6 +176,15 @@ const isWindowSpecificAPI = node => { return false; }; +/** +@param {import('estree').Node} node +@param {import('estree').Identifier} identifier +@returns +*/ +function isComputedMemberExpression(node, identifier) { + return node.type === 'MemberExpression' && node.computed && node.object === identifier; +} + /** Check if the node is a web worker specific API. @@ -194,6 +203,7 @@ const create = context => { if (node.type !== 'Identifier' || isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent) + || isComputedMemberExpression(node.parent, node) ) { return; } diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index d3b7be8fce..b2b8bc56ef 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -56,15 +56,15 @@ test.snapshot({ `, '({ foo: window.name } = {})', '[window.name] = []', + 'window[foo]', + 'window[title]', + 'window["foo"]', ], invalid: [ 'global', 'self', 'window', 'window.foo', - 'window[foo]', - 'window[title]', - 'window["foo"]', 'window.foo()', 'window > 10', '10 > window', diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 05bd25303f..6d28cc0658 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -88,70 +88,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(5): window[foo] - -> Input - - `␊ - 1 | window[foo]␊ - ` - -> Output - - `␊ - 1 | globalThis[foo]␊ - ` - -> Error 1/1 - - `␊ - > 1 | window[foo]␊ - | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ` - -## invalid(6): window[title] - -> Input - - `␊ - 1 | window[title]␊ - ` - -> Output - - `␊ - 1 | globalThis[title]␊ - ` - -> Error 1/1 - - `␊ - > 1 | window[title]␊ - | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ` - -## invalid(7): window["foo"] - -> Input - - `␊ - 1 | window["foo"]␊ - ` - -> Output - - `␊ - 1 | globalThis["foo"]␊ - ` - -> Error 1/1 - - `␊ - > 1 | window["foo"]␊ - | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ - ` - -## invalid(8): window.foo() +## invalid(5): window.foo() > Input @@ -172,7 +109,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(9): window > 10 +## invalid(6): window > 10 > Input @@ -193,7 +130,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(10): 10 > window +## invalid(7): 10 > window > Input @@ -214,7 +151,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(11): window ?? 10 +## invalid(8): window ?? 10 > Input @@ -235,7 +172,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(12): 10 ?? window +## invalid(9): 10 ?? window > Input @@ -256,7 +193,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(13): window.foo = 123 +## invalid(10): window.foo = 123 > Input @@ -277,7 +214,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(14): window = 123 +## invalid(11): window = 123 > Input @@ -298,7 +235,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(15): obj.a = window +## invalid(12): obj.a = window > Input @@ -319,7 +256,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(16): function* gen() { yield window } +## invalid(13): function* gen() { yield window } > Input @@ -346,7 +283,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(17): async function gen() { await window } +## invalid(14): async function gen() { await window } > Input @@ -373,7 +310,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(18): window ? foo : bar +## invalid(15): window ? foo : bar > Input @@ -394,7 +331,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(19): foo ? window : bar +## invalid(16): foo ? window : bar > Input @@ -415,7 +352,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(20): foo ? bar : window +## invalid(17): foo ? bar : window > Input @@ -436,7 +373,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(21): function foo() { return window } +## invalid(18): function foo() { return window } > Input @@ -463,7 +400,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(22): new window() +## invalid(19): new window() > Input @@ -484,7 +421,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(23): const obj = { foo: window.foo, bar: window.bar, window: window } +## invalid(20): const obj = { foo: window.foo, bar: window.bar, window: window } > Input @@ -539,7 +476,7 @@ Generated by [AVA](https://avajs.dev). 5 | }␊ ` -## invalid(24): function sequenceTest() { let x, y; x = (y = 10, y + 5, window); console.log(x, y); } +## invalid(21): function sequenceTest() { let x, y; x = (y = 10, y + 5, window); console.log(x, y); } > Input @@ -572,7 +509,7 @@ Generated by [AVA](https://avajs.dev). 5 | }␊ ` -## invalid(25): window`Hello ${42} World` +## invalid(22): window`Hello ${42} World` > Input @@ -593,7 +530,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(26): tag`Hello ${window.foo} World` +## invalid(23): tag`Hello ${window.foo} World` > Input @@ -614,7 +551,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(27): var str = `hello ${window.foo} world!` +## invalid(24): var str = `hello ${window.foo} world!` > Input @@ -635,7 +572,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(28): delete window.foo +## invalid(25): delete window.foo > Input @@ -656,7 +593,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(29): ++window +## invalid(26): ++window > Input @@ -677,7 +614,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(30): ++window.foo +## invalid(27): ++window.foo > Input @@ -698,7 +635,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(31): for (var attr in window) { } +## invalid(28): for (var attr in window) { } > Input @@ -725,7 +662,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(32): for (window.foo = 0; i < 10; window.foo++) { } +## invalid(29): for (window.foo = 0; i < 10; window.foo++) { } > Input @@ -761,7 +698,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(33): for (const item of window.foo) { } +## invalid(30): for (const item of window.foo) { } > Input @@ -785,7 +722,7 @@ Generated by [AVA](https://avajs.dev). 2 | }␊ ` -## invalid(34): for (const item of window) { } +## invalid(31): for (const item of window) { } > Input @@ -809,7 +746,7 @@ Generated by [AVA](https://avajs.dev). 2 | }␊ ` -## invalid(35): switch (window) {} +## invalid(32): switch (window) {} > Input @@ -830,7 +767,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(36): switch (true) { case window: break; } +## invalid(33): switch (true) { case window: break; } > Input @@ -860,7 +797,7 @@ Generated by [AVA](https://avajs.dev). 4 | }␊ ` -## invalid(37): switch (true) { case window.foo: break; } +## invalid(34): switch (true) { case window.foo: break; } > Input @@ -890,7 +827,7 @@ Generated by [AVA](https://avajs.dev). 4 | }␊ ` -## invalid(38): while (window) { } +## invalid(35): while (window) { } > Input @@ -914,7 +851,7 @@ Generated by [AVA](https://avajs.dev). 2 | }␊ ` -## invalid(39): do {} while (window) {} +## invalid(36): do {} while (window) {} > Input @@ -935,7 +872,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(40): if (window) {} +## invalid(37): if (window) {} > Input @@ -956,7 +893,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(41): throw window +## invalid(38): throw window > Input @@ -977,7 +914,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(42): var foo = window +## invalid(39): var foo = window > Input @@ -998,7 +935,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(43): function foo (name = window) { } +## invalid(40): function foo (name = window) { } > Input @@ -1025,7 +962,7 @@ Generated by [AVA](https://avajs.dev). 3 | }␊ ` -## invalid(44): self.innerWidth +## invalid(41): self.innerWidth > Input @@ -1046,7 +983,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^ Prefer \`globalThis\` over \`self\`.␊ ` -## invalid(45): self.innerHeight +## invalid(42): self.innerHeight > Input @@ -1067,7 +1004,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^ Prefer \`globalThis\` over \`self\`.␊ ` -## invalid(46): window.crypto +## invalid(43): window.crypto > Input @@ -1088,7 +1025,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(47): window.addEventListener("play", () => {}) +## invalid(44): window.addEventListener("play", () => {}) > Input @@ -1109,7 +1046,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(48): window.onplay = function () {} +## invalid(45): window.onplay = function () {} > Input @@ -1130,7 +1067,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(49): function greet({ name = window.foo }) {} +## invalid(46): function greet({ name = window.foo }) {} > Input @@ -1151,7 +1088,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(50): ({ foo: window.foo } = {}) +## invalid(47): ({ foo: window.foo } = {}) > Input @@ -1172,7 +1109,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(51): [window.foo] = [] +## invalid(48): [window.foo] = [] > Input @@ -1193,7 +1130,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(52): foo[window] +## invalid(49): foo[window] > Input @@ -1214,7 +1151,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` -## invalid(53): foo[window.foo] +## invalid(50): foo[window.foo] > Input diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 20450719c8ca0602ae6d2a44b43189625d710b58..056c16341c0ee4cb5b349e0d8430b04c782ad81d 100644 GIT binary patch literal 2520 zcmV;}2`BbJRzV)?@K7idI8hL>~4ZZ#8UX)D#_~m5c zCEkaZzPa-475;nXTPxpx=DVu^Z8#H8ud=`!v4FiD?jI!Lc|gzq06qV3&z}m+&aV!V z9P|zX4OfS%5deTQ_+L3A+YlY*f7xyd1OB}@j$&x9w?(x3S+t${0H!S1 z(PO=c-1v_0oj>a=(zg)kj)-(_B9F5qO8%rdMw!uWeE>&(IEjvIGnzjAlrt)fSY|YR z+8pg+7Hv;P+uVsFJz_e796?2W4Pkz)MXlg)%=d$qoDEwMo7vL)L z=|`FXwK^rib%c73lt3b}2=624o0Tj}q$t-4+^!Fx-GZTU=Fx0m@^+C@GpfL1*7V$aWQXRmAdeq zsNW zHt%1;xU2Ow*N1PEe#u2YC_`8Sh^*Kz@z zA@ayXJ~TLuvfys<%Qum{)Ck#;uxQ_bP%-wKNRGQq`L66P@WD-SuuZbw_gQw$(Svls!3M;g~&S z(`5c?30MNhYjCmw$FK>t6JCn8*5Cvh(9foDePbSb6tHFx?bi6?^$qGZ^k+1cj*BaL z(Rikz^dS?k%#|#qx<_S`{IAHfGpC;ASz5q5JmbGYBkq4Ii~BdUQVtEa<+d=k0qSp) z>vBkTWLdF&p9Mh#*G_w#89a*OV6v?bt96vTE2z342&nvb5ydN7kzuC6iTWMlc@NbZ z6o;#lqan59t&7ClmB#Y5$1GqEd3{|(U(Q0Qcn9&^BzW-4u~f=^L^cvqRyg%EHs4*T zEpJ8~dNE9s7&c*hkMQG&`*DTP_%#$xQ)pwyMrr+1#Md$N6(z@h zou%NiOabpWOjy7YR(kk(0|oNDP)7q&!Zr}}MGUn#3Z=_w-87Qx+!7r~g?P`Q(J)ekwh}o#EKISKj|jRTQxz}{hKC6HRzU?c z4$iMcT`Do}5=1f7_|)~1BnCgLjQOUH*qRNIqb=DVF>$0jjI!Rq>xi*uVpMiV23DIT zs?)B1V<8^uQsg(`6 zvQf|>2ASEvD zld5gxYE;<4si0d>MMFa}m~%8vY1j0G-I59Gl_#t@Z!DUVwz!}Q?*fUVHxYJ;v#^De zM|bI}lb0F#8WNbVO!KqxJwIT|45u>HL_tB;y(%Efmi-Q5xP}?*mwJY19%a2N-I1m0 z)~Y4_niP%~u#*T*XPRw7y;qUbFJ;v_4X4CwBZ8MH0*e*?Q^fL7R`eU(Al{G;Z*_Hf z9qjLv>qg(|!YKP&T^whj5`7b+U=$o4P|DswmsiBeUL0j7p|-sN6=UBUNKs4O3q=Ou z>D&wL-W83^w5l;FLdRCb+20Gzkrm3&`z6hAaT+uk9CL_Dx@9 ztD?bezI!MdhVy^yluzPb2Ptx&`MZ0G?IbSZmbrLG;BBrnYo=YOa#5<1e+1SX$0z#< z(FJ}P`SmQm@1BAvJ?Jw9MGpkUQv4cW@8O&70tb%H0%Z-+Q$7*%CX;)IEKJ_q}e6={DA>nvl})4Mf@3HMFM1`bLP?!}?lqy3$^DgL=yM zX;H}S!Dha$*62+ceGXgBVt)>+s9ervbMdjlDOY;-rJlFc7xHe*SW-I$^lF;-XlJyt zhR&EJ-vW(J17o3~J~OIa>`x3AbF}2u>|}#nsC+B<@$3o{acU<@8z?GwbMHQ literal 2599 zcmV+?3fT2QRzV@b0@WSeE@d*sqd}>wBbTLz0N#m#60%4e{>v)=K($c1N8iZLw6=H(_bA& zDd-&p8mga6x$zz0JAbyaNZ&%BJ0jABi8RifDEX7-7-dGg^#Po^{v+tENwhr~ZF3p~dc<@DDT0dnI>P)|i(0|q$nPWI>nQRCsG{gklj!?0`n_ooe5{9m z4SDoK6#fE2#s3ll{X~mj1!4i-L&!If05Pf}1s*?}NN_uqVDTG5gcp%lPh$~c5GBJ+ z1bbGO0YR}4zed=*SO|fuT#8pxDK@4-uu)cu7_^iW2wFl4fvZZ2XA&vypk<*}*Ok~n zZv9AG7;1G&h#Ls?47oH&B-Y`51btIm9BTE-mxouS3NVCrtK9OifGo2-s6hMWAx2d` z5ZbN!0NO1W8uvt60|jEQ!2(pUJAQzW_k;$jxmbh6Plby^yPXb(-Cc4tSDMOr!>tK~aGk&r3DBXrY81Xm`50 zB6Mt79Hq)FguFs7mRwa+Nq>@Ie8b6@0KCAOw1pUg;~CZ zA?^N?$<7NhJ9m^*2k-@Z03#>VQ$eo*Kz@zBl5sRJ~TLuvQXXPCl8Sw zUTXO4R9Lj{LZ}$~LnKF~ZX3D~^nn@~Oodr}SiUQ@;DyFG@MjS}qrncG^Yo~-$0na7 z@;^pSxGDZUAcpN1BAiDkoUu>>*%4#wQr4WvuRKV}cuELvUW6eJydH@995MZ4XGV(T|~}-G?uPC zW&wN1>l-5ad=^T@JBa5N!Gkx)Tq%zb*+@uP;M9{ie0Qa`ycu!ggfNRj*n#~+!jDt# z$2CIZ*HAc3p^Y6IrS(q{U&qXsl^k=P}gcngCr+>!y)hD@$}N72-XIM#EG?Uq#-1PehkIPw7DyF^xt+y-eSh zkcN`zE9~lbTT0~gurS4vKO*RYOjW=*7#<+#TNxG5I9OeYx>RD(B?v;O@u}-XQ3!5Q z8S_IOaWoquM_aN#V&aHT7kw;WcQtwv|Po(a5CZPlnl}h-b-KoS+mb`Bn+&mR+8*TX>wR>C9DGHAnACF^a zmYhfjFbbLT8QHa=_o570(s58Zlcva}m|L_4NQtxOq+%PX8U=Q6D(Dte*3gg)W`)Kn z?V6sj+cIIVxf2XT-BHqp<~P9?C*u9 z$O2{P^O9ybJB=#5XVL3s?pZ+1cRpv*wqY$dR6n^q#f5tI)3O}avfY%wAnLQ^cwgkO zvDB@)t8zsqq$fV^Yr4MA!iVl8I@I;2FYaex_Dx^qsG`AbzJ16VhSfg=R3>pBDRPgw z2ZxdEB+lZNxp+t5ZLTzHrmIlpvQ#DgVyrn1&yFIZ3!L|vlmIRBnG}ZFei<{^P_j%S;Tx6);5kj=WJsWYIWEd!ug!IzO;*+ZeyK_2`LTVK$Lx5 zLu*>BZ-96mtgi)URocsLP*3?rE%3QL*h$yb8ht3E-^1p!*uRHWRL<8}dQOSX4U)v^6byv~yZnLubsAuSBEMz?f;M&y8wl`xC=*j^=F5l^l?6%5Rf- zkx|pG`N5oDexeo=y3R5%n3j(|BDt9%$%>4Lu+A=G+7mkGxl?s-PQKIb^V(!DHTf~@ zz#j2+FTMY0K>Op(9u^G2ZAum0w9sgEapV`C{rGKKAZ%HG1g}6SLFj`b2c^!^Qv3!X zf0o_@m*%Q0VCDI@-$gn!=|2cy4oiVidejl{IZ}_N@ec$17NLKkY0^~wIKXPU{2yOO Jl6~t$006!x2~Pk3 From b96dbe9018b7ab8d290b542a7dd033d731c870f7 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Sat, 24 Aug 2024 20:06:26 +0800 Subject: [PATCH 61/70] update docs --- docs/rules/prefer-global-this.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/rules/prefer-global-this.md b/docs/rules/prefer-global-this.md index 5f834d52d2..34d565ff9f 100644 --- a/docs/rules/prefer-global-this.md +++ b/docs/rules/prefer-global-this.md @@ -43,11 +43,6 @@ global.foo; // ❌ globalThis.foo; // ✅ ``` -```js -global[foo]; // ❌ -globalThis[foo]; // ✅ -``` - ```js const {foo} = window; // ❌ const {foo} = globalThis; // ✅ From b76d42464dd25a260636bf29e4fa8add921fe680 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Sun, 25 Aug 2024 14:11:58 +0800 Subject: [PATCH 62/70] Revert "Discard changes to .github/workflows/title-formatter.yml" This reverts commit 45b5a995f6a590b5d240e624619b61955eadac46. --- .github/workflows/title-formatter.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/title-formatter.yml diff --git a/.github/workflows/title-formatter.yml b/.github/workflows/title-formatter.yml new file mode 100644 index 0000000000..f5a1e332c0 --- /dev/null +++ b/.github/workflows/title-formatter.yml @@ -0,0 +1,23 @@ +name: Title formatter + +on: + pull_request_target: + types: [opened, edited] + issues: + types: [opened, edited] + +jobs: + Rule: + runs-on: ubuntu-latest + permissions: + pull-requests: write + issues: write + steps: + - uses: actions/checkout@v4 + - name: Auto-format rule names in titles + uses: fregante/title-replacer-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + pattern-path: docs/rules + replacement: '`$0`' + trim-punctuation: true From 640c84b28b1f7c8a12bbacbba1be6a97f8643b46 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 10 Sep 2024 09:23:02 +0800 Subject: [PATCH 63/70] fix indent --- test/package.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/package.mjs b/test/package.mjs index 109c22602f..1a52e00628 100644 --- a/test/package.mjs +++ b/test/package.mjs @@ -32,7 +32,7 @@ const RULES_WITHOUT_PASS_FAIL_SECTIONS = new Set([ 'prefer-modern-math-apis', 'prefer-math-min-max', 'consistent-existence-index-check', - 'prefer-global-this', + 'prefer-global-this', ]); test('Every rule is defined in index file in alphabetical order', t => { From c73d1e5ad86426a294bb87212920452abf65fd6d Mon Sep 17 00:00:00 2001 From: Axetroy Date: Tue, 10 Sep 2024 20:15:50 +0800 Subject: [PATCH 64/70] refactor: remove GlobalReferenceTracker and use scope lookup --- rules/prefer-global-this.js | 80 ++++++++++--------------------------- 1 file changed, 22 insertions(+), 58 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index d95bc560eb..4ef7c32e80 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -1,8 +1,5 @@ 'use strict'; -const {GlobalReferenceTracker} = require('./utils/global-reference-tracker.js'); -const isShadowed = require('./utils/is-shadowed.js'); - const MESSAGE_ID_ERROR = 'prefer-global-this/error'; const messages = { [MESSAGE_ID_ERROR]: 'Prefer `globalThis` over `{{value}}`.', @@ -123,32 +120,6 @@ const webWorkerSpecificAPIs = new Set([ 'onconnect', ]); -/** -Report the node with a message. - -@param {import('estree').Node} node -*/ -function getProblem(node) { - return { - node, - messageId: MESSAGE_ID_ERROR, - data: {value: node.name}, - fix: (/** @type {import('eslint').Rule.RuleFixer} fixer */ fixer) => fixer.replaceText(node, 'globalThis'), - }; -} - -/** -Handle nodes and check if they should be reported. - -@param {import('eslint').Rule.RuleContext} context -@param {import('estree').Node} node -*/ -function handleNode(context, node) { - if (node.type === 'Identifier' && globalIdentifier.has(node.name) && !isShadowed(context.sourceCode.getScope(node), node)) { - return getProblem(node); - } -} - /** Check if the node is a window-specific API. @@ -194,36 +165,29 @@ Check if the node is a web worker specific API. const isWebWorkerSpecificAPI = node => node.type === 'MemberExpression' && node.object.name === 'self' && node.property.type === 'Identifier' && webWorkerSpecificAPIs.has(node.property.name); /** @param {import('eslint').Rule.RuleContext} context */ -const create = context => { - const tracker = new GlobalReferenceTracker({ - objects: globalIdentifier, - handle(reference) { - const {node} = reference; - - if (node.type !== 'Identifier' - || isWindowSpecificAPI(node.parent) - || isWebWorkerSpecificAPI(node.parent) - || isComputedMemberExpression(node.parent, node) - ) { - return; +const create = context => ({ + Program(programNode) { + const scope = context.sourceCode.getScope(programNode); + for (const variable of scope.variables) { + if (globalIdentifier.has(variable.name)) { + for (const reference of variable.references) { + const node = reference.identifier; + + if (isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent) || isComputedMemberExpression(node.parent, node)) { + continue; + } + + context.report({ + node, + messageId: MESSAGE_ID_ERROR, + data: {value: node.name}, + fix: fixer => fixer.replaceText(node, 'globalThis'), + }); + } } - - return getProblem(node); - }, - }); - - return { - ...tracker.createListeners(context), - /** @param {import('estree').AssignmentExpression} node */ - AssignmentExpression(node) { - return handleNode(context, node.left); - }, - /** @param {import('estree').UpdateExpression} node */ - UpdateExpression(node) { - return handleNode(context, node.argument); - }, - }; -}; + } + }, +}); /** @type {import('eslint').Rule.RuleModule} */ module.exports = { From a3a15bb00d1c04aa951f493ef04ab22a0f6edb85 Mon Sep 17 00:00:00 2001 From: Axetroy Date: Wed, 11 Sep 2024 13:55:59 +0800 Subject: [PATCH 65/70] fix: did not detect the global var when not declared at globals options --- rules/prefer-global-this.js | 40 +++++++++---- test/prefer-global-this.mjs | 33 +++++++++++ test/snapshots/prefer-global-this.mjs.md | 63 +++++++++++++++++++++ test/snapshots/prefer-global-this.mjs.snap | Bin 2520 -> 2656 bytes test/utils/test.mjs | 4 +- 5 files changed, 126 insertions(+), 14 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 4ef7c32e80..03b12ce418 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -164,28 +164,44 @@ Check if the node is a web worker specific API. */ const isWebWorkerSpecificAPI = node => node.type === 'MemberExpression' && node.object.name === 'self' && node.property.type === 'Identifier' && webWorkerSpecificAPIs.has(node.property.name); +/** + * + * @param {import('eslint').Rule.RuleContext} context + * @param {import('estree').Identifier} node + */ +function reportProblem(context, node) { + if (isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent) || isComputedMemberExpression(node.parent, node)) { + return; + } + + context.report({ + node, + messageId: MESSAGE_ID_ERROR, + data: {value: node.name}, + fix: fixer => fixer.replaceText(node, 'globalThis'), + }); +} + /** @param {import('eslint').Rule.RuleContext} context */ const create = context => ({ Program(programNode) { const scope = context.sourceCode.getScope(programNode); + + // Report variables declared at globals options for (const variable of scope.variables) { if (globalIdentifier.has(variable.name)) { for (const reference of variable.references) { - const node = reference.identifier; - - if (isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent) || isComputedMemberExpression(node.parent, node)) { - continue; - } - - context.report({ - node, - messageId: MESSAGE_ID_ERROR, - data: {value: node.name}, - fix: fixer => fixer.replaceText(node, 'globalThis'), - }); + reportProblem(context, reference.identifier); } } } + + // Report variables not declared at globals options + for (const reference of scope.through) { + if (globalIdentifier.has(reference.identifier.name)) { + reportProblem(context, reference.identifier); + } + } }, }); diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index b2b8bc56ef..404c1319fb 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -1,5 +1,6 @@ import {getTester} from './utils/test.mjs'; import outdent from 'outdent'; +import {normalizeLanguageOptions} from './utils/language-options.mjs'; const {test} = getTester(import.meta); @@ -171,3 +172,35 @@ test.snapshot({ ], }); +test.snapshot({ + testerOptions: { + languageOptions: { + globals: {}, // Without defined window/global/self, the rule should be able to detect them + }, + }, + // Define a custom languageOptionsMerger to test overriding the default languageOptionsMerger + languageOptionsMerger(languageOptionsA, languageOptionsB) { + languageOptionsA ??= {}; + languageOptionsB ??= {}; + + return normalizeLanguageOptions({ + ...languageOptionsA, + ...languageOptionsB, + parser: languageOptionsB.parser ?? languageOptionsA.parser, + globals: { + // Only use the globals from languageOptionsB + ...languageOptionsB.globals, + }, + parserOptions: { + ...languageOptionsA.parserOptions, + ...languageOptionsB.parserOptions, + }, + }); + }, + valid: [], + invalid: [ + 'global.global_did_not_declare_in_language_options', + 'window.window_did_not_declare_in_language_options', + 'self.self_did_not_declare_in_language_options', + ], +}); diff --git a/test/snapshots/prefer-global-this.mjs.md b/test/snapshots/prefer-global-this.mjs.md index 6d28cc0658..27876df9b4 100644 --- a/test/snapshots/prefer-global-this.mjs.md +++ b/test/snapshots/prefer-global-this.mjs.md @@ -1171,3 +1171,66 @@ Generated by [AVA](https://avajs.dev). > 1 | foo[window.foo]␊ | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ ` + +## invalid(1): global.global_did_not_declare_in_language_options + +> Input + + `␊ + 1 | global.global_did_not_declare_in_language_options␊ + ` + +> Output + + `␊ + 1 | globalThis.global_did_not_declare_in_language_options␊ + ` + +> Error 1/1 + + `␊ + > 1 | global.global_did_not_declare_in_language_options␊ + | ^^^^^^ Prefer \`globalThis\` over \`global\`.␊ + ` + +## invalid(2): window.window_did_not_declare_in_language_options + +> Input + + `␊ + 1 | window.window_did_not_declare_in_language_options␊ + ` + +> Output + + `␊ + 1 | globalThis.window_did_not_declare_in_language_options␊ + ` + +> Error 1/1 + + `␊ + > 1 | window.window_did_not_declare_in_language_options␊ + | ^^^^^^ Prefer \`globalThis\` over \`window\`.␊ + ` + +## invalid(3): self.self_did_not_declare_in_language_options + +> Input + + `␊ + 1 | self.self_did_not_declare_in_language_options␊ + ` + +> Output + + `␊ + 1 | globalThis.self_did_not_declare_in_language_options␊ + ` + +> Error 1/1 + + `␊ + > 1 | self.self_did_not_declare_in_language_options␊ + | ^^^^ Prefer \`globalThis\` over \`self\`.␊ + ` diff --git a/test/snapshots/prefer-global-this.mjs.snap b/test/snapshots/prefer-global-this.mjs.snap index 056c16341c0ee4cb5b349e0d8430b04c782ad81d..bb7dac19578a0da3345aaa331ce10ee74a96cb29 100644 GIT binary patch literal 2656 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 diff --git a/test/utils/test.mjs b/test/utils/test.mjs index 638a22536b..0549be5411 100644 --- a/test/utils/test.mjs +++ b/test/utils/test.mjs @@ -93,14 +93,14 @@ class Tester { } snapshot(tests) { - let {testerOptions = {}, valid, invalid} = tests; + let {testerOptions = {}, languageOptionsMerger = mergeLanguageOptions, valid, invalid} = tests; valid = valid.map(testCase => normalizeTestCase(testCase)); invalid = invalid.map(testCase => normalizeTestCase(testCase)); const testConfig = { ...testerOptions, - languageOptions: mergeLanguageOptions(DEFAULT_LANGUAGE_OPTIONS, testerOptions.languageOptions), + languageOptions: languageOptionsMerger(DEFAULT_LANGUAGE_OPTIONS, testerOptions.languageOptions), }; const tester = new SnapshotRuleTester(test, testConfig); From 12fe9a4cb9852cf5ac68ace147c6621a811b56bc Mon Sep 17 00:00:00 2001 From: Axetroy Date: Wed, 11 Sep 2024 14:04:37 +0800 Subject: [PATCH 66/70] style jsdoc --- rules/prefer-global-this.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index 03b12ce418..fb1b8f6396 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -165,10 +165,9 @@ Check if the node is a web worker specific API. const isWebWorkerSpecificAPI = node => node.type === 'MemberExpression' && node.object.name === 'self' && node.property.type === 'Identifier' && webWorkerSpecificAPIs.has(node.property.name); /** - * - * @param {import('eslint').Rule.RuleContext} context - * @param {import('estree').Identifier} node - */ +@param {import('eslint').Rule.RuleContext} context +@param {import('estree').Identifier} node +*/ function reportProblem(context, node) { if (isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent) || isComputedMemberExpression(node.parent, node)) { return; From 84147cdace505cfde26cb2b4ab0cae438c94ae2a Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 27 Sep 2024 21:47:51 +0800 Subject: [PATCH 67/70] Revert tester change --- test/prefer-global-this.mjs | 21 +-------------------- test/utils/test.mjs | 4 ++-- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index 404c1319fb..fea1acf465 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -175,28 +175,9 @@ test.snapshot({ test.snapshot({ testerOptions: { languageOptions: { - globals: {}, // Without defined window/global/self, the rule should be able to detect them + globals: {global: 'off', window: 'off', self: 'off'}, }, }, - // Define a custom languageOptionsMerger to test overriding the default languageOptionsMerger - languageOptionsMerger(languageOptionsA, languageOptionsB) { - languageOptionsA ??= {}; - languageOptionsB ??= {}; - - return normalizeLanguageOptions({ - ...languageOptionsA, - ...languageOptionsB, - parser: languageOptionsB.parser ?? languageOptionsA.parser, - globals: { - // Only use the globals from languageOptionsB - ...languageOptionsB.globals, - }, - parserOptions: { - ...languageOptionsA.parserOptions, - ...languageOptionsB.parserOptions, - }, - }); - }, valid: [], invalid: [ 'global.global_did_not_declare_in_language_options', diff --git a/test/utils/test.mjs b/test/utils/test.mjs index 0549be5411..638a22536b 100644 --- a/test/utils/test.mjs +++ b/test/utils/test.mjs @@ -93,14 +93,14 @@ class Tester { } snapshot(tests) { - let {testerOptions = {}, languageOptionsMerger = mergeLanguageOptions, valid, invalid} = tests; + let {testerOptions = {}, valid, invalid} = tests; valid = valid.map(testCase => normalizeTestCase(testCase)); invalid = invalid.map(testCase => normalizeTestCase(testCase)); const testConfig = { ...testerOptions, - languageOptions: languageOptionsMerger(DEFAULT_LANGUAGE_OPTIONS, testerOptions.languageOptions), + languageOptions: mergeLanguageOptions(DEFAULT_LANGUAGE_OPTIONS, testerOptions.languageOptions), }; const tester = new SnapshotRuleTester(test, testConfig); From 496483e66c1cbdddabdc88ded2b132d57b8c539b Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 27 Sep 2024 21:58:12 +0800 Subject: [PATCH 68/70] Simplify --- rules/prefer-global-this.js | 55 ++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index fb1b8f6396..edd18eb560 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -164,42 +164,33 @@ Check if the node is a web worker specific API. */ const isWebWorkerSpecificAPI = node => node.type === 'MemberExpression' && node.object.name === 'self' && node.property.type === 'Identifier' && webWorkerSpecificAPIs.has(node.property.name); -/** -@param {import('eslint').Rule.RuleContext} context -@param {import('estree').Identifier} node -*/ -function reportProblem(context, node) { - if (isWindowSpecificAPI(node.parent) || isWebWorkerSpecificAPI(node.parent) || isComputedMemberExpression(node.parent, node)) { - return; - } - - context.report({ - node, - messageId: MESSAGE_ID_ERROR, - data: {value: node.name}, - fix: fixer => fixer.replaceText(node, 'globalThis'), - }); -} - /** @param {import('eslint').Rule.RuleContext} context */ const create = context => ({ - Program(programNode) { - const scope = context.sourceCode.getScope(programNode); - - // Report variables declared at globals options - for (const variable of scope.variables) { - if (globalIdentifier.has(variable.name)) { - for (const reference of variable.references) { - reportProblem(context, reference.identifier); - } + * Program(program) { + const scope = context.sourceCode.getScope(program); + + const references = [ + // Variables declared at globals options + ...scope.variables.flatMap(variable => globalIdentifier.has(variable.name) ? variable.references : []), + // Variables not declared at globals options + ...scope.through.filter(reference => globalIdentifier.has(reference.identifier.name)), + ]; + + for (const {identifier} of references) { + if ( + isComputedMemberExpression(identifier.parent, identifier) + || isWindowSpecificAPI(identifier.parent) + || isWebWorkerSpecificAPI(identifier.parent) + ) { + continue; } - } - // Report variables not declared at globals options - for (const reference of scope.through) { - if (globalIdentifier.has(reference.identifier.name)) { - reportProblem(context, reference.identifier); - } + yield { + node: identifier, + messageId: MESSAGE_ID_ERROR, + data: {value: identifier.name}, + fix: fixer => fixer.replaceText(identifier, 'globalThis'), + }; } }, }); From 775288d902e9ded1cf92f79c75f0e6b142a08ae3 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 27 Sep 2024 22:01:00 +0800 Subject: [PATCH 69/70] Minor tweak --- rules/prefer-global-this.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/rules/prefer-global-this.js b/rules/prefer-global-this.js index edd18eb560..ce1104e3e6 100644 --- a/rules/prefer-global-this.js +++ b/rules/prefer-global-this.js @@ -148,12 +148,11 @@ const isWindowSpecificAPI = node => { }; /** -@param {import('estree').Node} node @param {import('estree').Identifier} identifier -@returns +@returns {boolean} */ -function isComputedMemberExpression(node, identifier) { - return node.type === 'MemberExpression' && node.computed && node.object === identifier; +function isComputedMemberExpressionObject(identifier) { + return identifier.parent.type === 'MemberExpression' && identifier.parent.computed && identifier.parent.object === identifier; } /** @@ -178,7 +177,7 @@ const create = context => ({ for (const {identifier} of references) { if ( - isComputedMemberExpression(identifier.parent, identifier) + isComputedMemberExpressionObject(identifier) || isWindowSpecificAPI(identifier.parent) || isWebWorkerSpecificAPI(identifier.parent) ) { From 8922b37d212e77bc9d8c0ab5af4f7824ba5671b7 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 27 Sep 2024 22:06:05 +0800 Subject: [PATCH 70/70] Linting --- test/prefer-global-this.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/prefer-global-this.mjs b/test/prefer-global-this.mjs index fea1acf465..879ea2cb0f 100644 --- a/test/prefer-global-this.mjs +++ b/test/prefer-global-this.mjs @@ -1,6 +1,5 @@ import {getTester} from './utils/test.mjs'; import outdent from 'outdent'; -import {normalizeLanguageOptions} from './utils/language-options.mjs'; const {test} = getTester(import.meta);