Skip to content

Commit 7396916

Browse files
Merge pull request #2673 from johanrd/night_fix/template-require-has-block-helper
Post-merge-review: Fix `template-require-has-block-helper`: skip JS scope bindings
2 parents a1ab781 + 103e082 commit 7396916

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

lib/rules/template-require-has-block-helper.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,38 @@ module.exports = {
5050
},
5151

5252
create(context) {
53+
const sourceCode = context.sourceCode;
54+
55+
// Returns true if the identifier resolves to a JS binding. In GJS/GTS a
56+
// user can legitimately `import { hasBlock } from 'somewhere'`; rewriting
57+
// their reference to the `has-block` keyword would change semantics.
58+
// Note: `node` here is the GlimmerPathExpression itself (this visitor is
59+
// on PathExpression directly, not a wrapping MustacheStatement), so we
60+
// read `node.original` rather than `node.path.original`.
61+
function isJsScopeVariable(node) {
62+
if (!sourceCode || !node.original) {
63+
return false;
64+
}
65+
const name = node.original;
66+
try {
67+
let scope = sourceCode.getScope(node);
68+
while (scope) {
69+
if (scope.variables.some((v) => v.name === name)) {
70+
return true;
71+
}
72+
scope = scope.upper;
73+
}
74+
} catch {
75+
// sourceCode.getScope may not be available in .hbs-only mode; ignore.
76+
}
77+
return false;
78+
}
79+
5380
return {
5481
GlimmerPathExpression(node) {
5582
const replacement = TRANSFORMATIONS[node.original];
5683

57-
if (replacement) {
84+
if (replacement && !isJsScopeVariable(node)) {
5885
context.report({
5986
node,
6087
message: getErrorMessage(node.original),

tests/lib/rules/template-require-has-block-helper.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,15 @@ const gjsRuleTester = new RuleTester({
166166
});
167167

168168
gjsRuleTester.run('template-require-has-block-helper', rule, {
169-
valid: validHbs.map(wrapTemplate),
169+
valid: [
170+
...validHbs.map(wrapTemplate),
171+
// GJS/GTS: an imported/local hasBlock binding is a user's own reference,
172+
// not the Glimmer built-in — rewriting to `has-block` would change semantics.
173+
`import hasBlock from './my-has-block';
174+
export default <template>{{hasBlock}}</template>;`,
175+
`const hasBlockParams = () => true;
176+
export default <template>{{hasBlockParams}}</template>;`,
177+
],
170178
invalid: invalidHbs.map((test) => ({
171179
code: wrapTemplate(test.code),
172180
output: wrapTemplate(test.output),

0 commit comments

Comments
 (0)