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

+23-2
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

+13
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)