Skip to content

Commit b636fb8

Browse files
committed
sync(is-native-element): canonical update — use binding resolution for scope-shadowing (Copilot review)
1 parent 65a7d92 commit b636fb8

1 file changed

Lines changed: 20 additions & 5 deletions

File tree

lib/utils/is-native-element.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,31 @@ function isNativeElement(node, sourceCode) {
6060
}
6161
const scope = sourceCode.getScope(node.parent);
6262
const firstPart = node.parts && node.parts[0];
63-
// Compare by identifier name rather than AST node object identity — object
64-
// identity isn't guaranteed across parser versions (ember-eslint-parser can
65-
// produce distinct node objects for the same token depending on how the
66-
// scope manager walks the tree), but the resolved `.name` is stable.
67-
if (firstPart && scope.references.some((ref) => ref.identifier?.name === firstPart?.name)) {
63+
// Scope-shadowing detection: treat the tag as a component invocation only
64+
// when its name resolves to an actual BINDING (const / let / import / block-
65+
// param) in the enclosing scope chain — not just any reference. A bare
66+
// reference like `{{div}}` (helper invocation elsewhere in the template)
67+
// creates an entry in `scope.references` without binding a local
68+
// identifier; it must not shadow the native `<div>` tag. Walking upward
69+
// through `scope.upper` catches bindings declared in outer scopes — e.g.
70+
// a module-level `const div = ...` shadowing templates deeper in the file.
71+
if (firstPart && hasBindingInScopeChain(scope, firstPart.name)) {
6872
return false;
6973
}
7074
return true;
7175
}
7276

77+
function hasBindingInScopeChain(scope, name) {
78+
let current = scope;
79+
while (current) {
80+
if (current.variables && current.variables.some((v) => v.name === name)) {
81+
return true;
82+
}
83+
current = current.upper;
84+
}
85+
return false;
86+
}
87+
7388
/**
7489
* Inverse of {@link isNativeElement}. Returns true when the node should NOT
7590
* be treated as a native HTML element — either because it's a component

0 commit comments

Comments
 (0)