Skip to content

Post-merge-review: Fix template-no-unbound false positive in GJS/GTS#2668

Open
johanrd wants to merge 1 commit intoember-cli:masterfrom
johanrd:night_fix/template-no-unbound
Open

Post-merge-review: Fix template-no-unbound false positive in GJS/GTS#2668
johanrd wants to merge 1 commit intoember-cli:masterfrom
johanrd:night_fix/template-no-unbound

Conversation

@johanrd
Copy link
Copy Markdown
Contributor

@johanrd johanrd commented Apr 13, 2026

What's broken on master

Flags {{unbound}} as the classic Ember resolver-resolved helper, but doesn't account for JS-scope shadowing in GJS/GTS strict mode. A user-imported unbound (import unbound from './my-unbound-helper') or a block-param unbound ({{#let (...) as |unbound|}}) is incorrectly flagged.

Why a JS-scope check (not an .hbs-only gate)

unbound is an ambient strict-mode keyword in Glimmer/Ember — registered in STRICT_MODE_KEYWORDS and backed by BUILTIN_KEYWORD_HELPERS.unbound. So <template>{{unbound foo}}</template> works in .gjs/.gts without an import. Gating the rule to .hbs would hide the very thing the rule exists to flag (false negative).

Fix

Mirror the template-no-log pattern: walk sourceCode.getScope().variables to detect JS bindings, plus track template block params, and skip reporting only when the identifier resolves to a local. Update templateMode from 'loose' to 'both' to reflect that the rule now runs in strict mode.

Test plan

13/13 tests pass on the branch.

  • Bare {{unbound foo}} in .gjs is now correctly flagged again (would have been a false negative under an .hbs-only gate).
  • import unbound from '...'; {{unbound foo}} in .gjs/.gts is correctly skipped (JS-scope binding).
  • {{#let (...) as |unbound|}}{{unbound}}{{/let}} is correctly skipped (block-param shadowing).
  • All HBS cases unchanged.

@johanrd johanrd marked this pull request as ready for review April 13, 2026 10:30
@johanrd johanrd marked this pull request as draft April 13, 2026 10:30
@johanrd johanrd force-pushed the night_fix/template-no-unbound branch from 7f08d51 to e5b3dfc Compare April 13, 2026 10:40
@johanrd johanrd marked this pull request as ready for review April 13, 2026 11:08
@johanrd johanrd force-pushed the night_fix/template-no-unbound branch 2 times, most recently from 2a9f19b to 7da211d Compare April 13, 2026 14:40
`unbound` is an ambient strict-mode keyword in Glimmer/Ember (registered
in STRICT_MODE_KEYWORDS, backed by BUILTIN_KEYWORD_HELPERS.unbound), so
`{{unbound foo}}` works in .gjs/.gts without an import. The rule should
still flag those uses everywhere — but skip when `unbound` resolves to
a JS binding or template block param.

ember-eslint-parser registers template block params in scope, so a
single sourceCode.getScope walk covers both JS bindings and block
params. Also updates templateMode from 'loose' to 'both' so the rule
runs in strict mode.
@johanrd johanrd force-pushed the night_fix/template-no-unbound branch from 7da211d to 597f0d5 Compare April 13, 2026 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant