Skip to content

Commit 8f9e481

Browse files
committed
🐛 fix reference tracker false positive
See also eslint/eslint#12437.
1 parent 6633278 commit 8f9e481

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

src/reference-tracker.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { findVariable } from "./find-variable"
22
import { getPropertyName } from "./get-property-name"
33
import { getStringIfConstant } from "./get-string-if-constant"
44

5-
const SENTINEL_TYPE = /^(?:.+?Statement|.+?Declaration|(?:Array|ArrowFunction|Assignment|Call|Class|Function|Member|New|Object)Expression|AssignmentPattern|Program|VariableDeclarator)$/u
65
const IMPORT_TYPE = /^(?:Import|Export(?:All|Default|Named))Declaration$/u
76
const has = Function.call.bind(Object.hasOwnProperty)
87

@@ -26,6 +25,28 @@ function isModifiedGlobal(variable) {
2625
)
2726
}
2827

28+
/**
29+
* Check if the value of a given node is passed through to the parent syntax as-is.
30+
* For example, `a` and `b` in (`a || b` and `c ? a : b`) are passed through.
31+
* @param {Node} node A node to check.
32+
* @returns {boolean} `true` if the node is passed through.
33+
*/
34+
function isPassThrough(node) {
35+
const parent = node.parent
36+
37+
switch (parent && parent.type) {
38+
case "ConditionalExpression":
39+
return parent.consequent === node || parent.alternate === node
40+
case "LogicalExpression":
41+
return true
42+
case "SequenceExpression":
43+
return parent.expressions[parent.expressions.length - 1] === node
44+
45+
default:
46+
return false
47+
}
48+
}
49+
2950
/**
3051
* The reference tracker.
3152
*/
@@ -227,7 +248,7 @@ export class ReferenceTracker {
227248
//eslint-disable-next-line complexity
228249
*_iteratePropertyReferences(rootNode, path, traceMap) {
229250
let node = rootNode
230-
while (!SENTINEL_TYPE.test(node.parent.type)) {
251+
while (isPassThrough(node)) {
231252
node = node.parent
232253
}
233254

test/reference-tracker.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { CALL, CONSTRUCT, ESM, READ, ReferenceTracker } from "../src/"
44

55
const config = {
66
parserOptions: { ecmaVersion: 2018, sourceType: "module" },
7+
globals: { Reflect: false },
78
rules: { test: "error" },
89
}
910

@@ -369,6 +370,18 @@ describe("The 'ReferenceTracker' class:", () => {
369370
},
370371
expected: [],
371372
},
373+
{
374+
description:
375+
"should not iterate the references through unary/binary expressions.",
376+
code: [
377+
'var construct = typeof Reflect !== "undefined" ? Reflect.construct : undefined',
378+
"construct()",
379+
].join("\n"),
380+
traceMap: {
381+
Reflect: { [CALL]: 1 },
382+
},
383+
expected: [],
384+
},
372385
]) {
373386
it(description, () => {
374387
const linter = new eslint.Linter()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy