Skip to content

Commit 76a77ad

Browse files
committed
add test and refactor
1 parent 14808d9 commit 76a77ad

22 files changed

+428
-20
lines changed

packages/eslint-plugin-svelte/src/rules/no-top-level-browser-globals.ts

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ export default createRule('no-top-level-browser-globals', {
8181
for (const ref of referenceTracker.iterateEsmReferences({
8282
'esm-env': {
8383
[ReferenceTracker.ESM]: true,
84+
// See https://www.npmjs.com/package/esm-env
8485
BROWSER: {
8586
[ReferenceTracker.READ]: true
8687
}
8788
},
8889
'$app/environment': {
8990
[ReferenceTracker.ESM]: true,
91+
// See https://svelte.dev/docs/kit/$app-environment#browser
9092
browser: {
9193
[ReferenceTracker.READ]: true
9294
}
@@ -107,6 +109,22 @@ export default createRule('no-top-level-browser-globals', {
107109
}
108110
}
109111

112+
/**
113+
* Iterate over the used references of global variables.
114+
*/
115+
function* iterateBrowserGlobalReferences(): Iterable<TrackedReferences<unknown>> {
116+
yield* referenceTracker.iterateGlobalReferences(
117+
Object.fromEntries(
118+
blowerGlobals.map((name) => [
119+
name,
120+
{
121+
[ReferenceTracker.READ]: true
122+
}
123+
])
124+
)
125+
);
126+
}
127+
110128
// Collects guarded location checkers by checking module references
111129
// that can check the browser environment.
112130
for (const referenceNode of iterateBrowserCheckerModuleReferences()) {
@@ -123,16 +141,7 @@ export default createRule('no-top-level-browser-globals', {
123141
const reportCandidates: TrackedReferences<unknown>[] = [];
124142

125143
// Collects references to global variables.
126-
for (const ref of referenceTracker.iterateGlobalReferences({
127-
...Object.fromEntries(
128-
blowerGlobals.map((name) => [
129-
name,
130-
{
131-
[ReferenceTracker.READ]: true
132-
}
133-
])
134-
)
135-
})) {
144+
for (const ref of iterateBrowserGlobalReferences()) {
136145
if (!isTopLevelLocation(ref.node)) continue;
137146
const guardChecker = getGuardCheckerFromReference(ref.node);
138147
if (guardChecker) {
@@ -189,9 +198,8 @@ export default createRule('no-top-level-browser-globals', {
189198
if (!operand) return null;
190199

191200
const staticValue = getStaticValue(operand, getScope(context, operand));
192-
if (!staticValue) {
193-
return null;
194-
}
201+
if (!staticValue) return null;
202+
195203
if (staticValue.value === undefined && node.type === 'MemberExpression') {
196204
if (parent.operator === '!==' || parent.operator === '!=') {
197205
// e.g. if (globalThis.window !== undefined), if (globalThis.window != undefined)
@@ -224,9 +232,8 @@ export default createRule('no-top-level-browser-globals', {
224232
pp.left === parent ? pp.right : pp.left,
225233
getScope(context, node)
226234
);
227-
if (!staticValue) {
228-
return null;
229-
}
235+
if (!staticValue) return null;
236+
230237
if (staticValue.value !== 'undefined' && staticValue.value !== 'object') {
231238
return null;
232239
}
@@ -264,9 +271,8 @@ export default createRule('no-top-level-browser-globals', {
264271
not?: boolean;
265272
}): ((node: TSESTree.Node) => boolean) | null {
266273
const parent = guardInfo.node.parent;
267-
if (!parent) {
268-
return null;
269-
}
274+
if (!parent) return null;
275+
270276
if (parent.type === 'ConditionalExpression') {
271277
const block = guardInfo.not ? parent.alternate : parent.consequent;
272278
return (n) => block.range[0] <= n.range[0] && n.range[1] <= block.range[1];
@@ -279,7 +285,6 @@ export default createRule('no-top-level-browser-globals', {
279285
const block = parent.consequent;
280286
return (n) => block.range[0] <= n.range[0] && n.range[1] <= block.range[1];
281287
}
282-
// e.g. if (typeof x === 'undefined')
283288
if (parent.alternate) {
284289
const block = parent.alternate;
285290
return (n) => block.range[0] <= n.range[0] && n.range[1] <= block.range[1];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- message: Unexpected top-level browser global variable "location".
2+
line: 8
3+
column: 15
4+
suggestions: null
5+
- message: Unexpected top-level browser global variable "location".
6+
line: 13
7+
column: 15
8+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script>
2+
import { browser } from '$app/environment';
3+
import * as env from '$app/environment';
4+
5+
if (browser) {
6+
console.log(location.href);
7+
} else {
8+
console.log(location.href); // NG
9+
}
10+
if (env.browser) {
11+
console.log(location.href);
12+
} else {
13+
console.log(location.href); // NG
14+
}
15+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- message: Unexpected top-level browser global variable "location".
2+
line: 8
3+
column: 15
4+
suggestions: null
5+
- message: Unexpected top-level browser global variable "location".
6+
line: 13
7+
column: 15
8+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script>
2+
import { BROWSER } from 'esm-env';
3+
import * as env from 'esm-env';
4+
5+
if (BROWSER) {
6+
console.log(location.href);
7+
} else {
8+
console.log(location.href); // NG
9+
}
10+
if (env.BROWSER) {
11+
console.log(location.href);
12+
} else {
13+
console.log(location.href); // NG
14+
}
15+
</script>

packages/eslint-plugin-svelte/tests/fixtures/rules/no-top-level-browser-globals/invalid/guards01-errors.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,7 @@
3838
line: 50
3939
column: 15
4040
suggestions: null
41+
- message: Unexpected top-level browser global variable "location".
42+
line: 55
43+
column: 15
44+
suggestions: null

packages/eslint-plugin-svelte/tests/fixtures/rules/no-top-level-browser-globals/invalid/guards01-input.svelte

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,9 @@
4949
} else {
5050
console.log(location.href); // NG
5151
}
52+
if ('undefined' !== typeof window) {
53+
console.log(location.href);
54+
} else {
55+
console.log(location.href); // NG
56+
}
5257
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
- message: Unexpected top-level browser global variable "location".
2+
line: 5
3+
column: 15
4+
suggestions: null
5+
- message: Unexpected top-level browser global variable "location".
6+
line: 10
7+
column: 15
8+
suggestions: null
9+
- message: Unexpected top-level browser global variable "location".
10+
line: 15
11+
column: 15
12+
suggestions: null
13+
- message: Unexpected top-level browser global variable "location".
14+
line: 18
15+
column: 15
16+
suggestions: null
17+
- message: Unexpected top-level browser global variable "location".
18+
line: 25
19+
column: 15
20+
suggestions: null
21+
- message: Unexpected top-level browser global variable "location".
22+
line: 28
23+
column: 15
24+
suggestions: null
25+
- message: Unexpected top-level browser global variable "location".
26+
line: 35
27+
column: 15
28+
suggestions: null
29+
- message: Unexpected top-level browser global variable "location".
30+
line: 38
31+
column: 15
32+
suggestions: null
33+
- message: Unexpected top-level browser global variable "location".
34+
line: 42
35+
column: 6
36+
suggestions: null
37+
- message: Unexpected top-level browser global variable "location".
38+
line: 44
39+
column: 15
40+
suggestions: null
41+
- message: Unexpected top-level browser global variable "location".
42+
line: 46
43+
column: 15
44+
suggestions: null
45+
- message: Unexpected top-level browser global variable "location".
46+
line: 48
47+
column: 6
48+
suggestions: null
49+
- message: Unexpected top-level browser global variable "location".
50+
line: 50
51+
column: 15
52+
suggestions: null
53+
- message: Unexpected top-level browser global variable "location".
54+
line: 52
55+
column: 15
56+
suggestions: null
57+
- message: Unexpected top-level browser global variable "location".
58+
line: 57
59+
column: 15
60+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<script>
2+
if (globalThis.window !== undefined) {
3+
console.log(location.href);
4+
} else {
5+
console.log(location.href); // NG
6+
}
7+
if (globalThis.document !== undefined) {
8+
console.log(location.href);
9+
} else {
10+
console.log(location.href); // NG
11+
}
12+
if (globalThis.location !== undefined) {
13+
console.log(location.href);
14+
} else {
15+
console.log(location.href); // NG
16+
}
17+
if (globalThis.location === undefined) {
18+
console.log(location.href); // NG
19+
} else {
20+
console.log(location.href);
21+
}
22+
if (globalThis.location != undefined) {
23+
console.log(location.href);
24+
} else {
25+
console.log(location.href); // NG
26+
}
27+
if (globalThis.location == undefined) {
28+
console.log(location.href); // NG
29+
} else {
30+
console.log(location.href);
31+
}
32+
if (globalThis.location != null) {
33+
console.log(location.href);
34+
} else {
35+
console.log(location.href); // NG
36+
}
37+
if (globalThis.location == null) {
38+
console.log(location.href); // NG
39+
} else {
40+
console.log(location.href);
41+
}
42+
if (globalThis.location !== null) {
43+
// NG
44+
console.log(location.href); // NG
45+
} else {
46+
console.log(location.href); // NG
47+
}
48+
if (globalThis.location === null) {
49+
// NG
50+
console.log(location.href); // NG
51+
} else {
52+
console.log(location.href); // NG
53+
}
54+
if (undefined !== globalThis.window) {
55+
console.log(location.href);
56+
} else {
57+
console.log(location.href); // NG
58+
}
59+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
- message: Unexpected top-level browser global variable "location".
2+
line: 5
3+
column: 15
4+
suggestions: null
5+
- message: Unexpected top-level browser global variable "location".
6+
line: 10
7+
column: 15
8+
suggestions: null
9+
- message: Unexpected top-level browser global variable "location".
10+
line: 15
11+
column: 15
12+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script>
2+
if (globalThis.window instanceof Object) {
3+
console.log(location.href);
4+
} else {
5+
console.log(location.href); // NG
6+
}
7+
if (globalThis.document instanceof Object) {
8+
console.log(location.href);
9+
} else {
10+
console.log(location.href); // NG
11+
}
12+
if (globalThis.location instanceof Object) {
13+
console.log(location.href);
14+
} else {
15+
console.log(location.href); // NG
16+
}
17+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- message: Unexpected top-level browser global variable "location".
2+
line: 3
3+
column: 31
4+
suggestions: null
5+
- message: Unexpected top-level browser global variable "location".
6+
line: 4
7+
column: 25
8+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
import { browser } from '$app/environment';
3+
console.log(browser ? null : location.href); // NG
4+
console.log(!browser ? location.href : null); // NG
5+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- message: Unexpected top-level browser global variable "location".
2+
line: 9
3+
column: 15
4+
suggestions: null
5+
- message: Unexpected top-level browser global variable "location".
6+
line: 13
7+
column: 16
8+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<script>
2+
import { browser } from '$app/environment';
3+
4+
for (const x of []) {
5+
if (browser) {
6+
console.log(location.href);
7+
continue;
8+
}
9+
console.log(location.href); // NG
10+
}
11+
for (const x of []) {
12+
if (!browser) {
13+
console.log(location.href); // NG
14+
continue;
15+
}
16+
console.log(location.href);
17+
}
18+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- message: Unexpected top-level browser global variable "location".
2+
line: 13
3+
column: 15
4+
suggestions: null
5+
- message: Unexpected top-level browser global variable "location".
6+
line: 17
7+
column: 16
8+
suggestions: null

0 commit comments

Comments
 (0)