Post-merge-review: Fix template-no-attrs-in-components: align detection with upstream#2688
Merged
NullVoxPopuli merged 7 commits intoember-cli:masterfrom Apr 15, 2026
Conversation
The port flagged this.attrs.* (which is not a real Ember API) and ran on all templates. Upstream gates on file path (templates/components/, components/*/template, ui/components/, -components/) and flags bare attrs.* — the pre-Octane args-leakage pattern. Restore upstream's behavior.
1577807 to
11afc7a
Compare
| }, | ||
| // `this.attrs.*` is not a real Ember API, but it is NOT what this rule | ||
| // targets — only bare `attrs.*` is flagged. So outside of a component | ||
| // template, `this.attrs.*` should not be flagged. |
Contributor
There was a problem hiding this comment.
it should be flagged, unless there is another lint rule that would cover it.
This is from @ember/component components.
Contributor
Author
There was a problem hiding this comment.
Thanks, should be fixed now. The PR was using original.startsWith('attrs.') which misses it. In the Glimmer AST, this.attrs.foo has parts[0] === 'attrs' (this is the receiver, not a part), so switching to parts[0] === 'attrs' catches both forms.
Contributor
There was a problem hiding this comment.
I didn't see any tests with this.attrs -- did I miss them?
Contributor
Author
There was a problem hiding this comment.
NullVoxPopuli
requested changes
Apr 14, 2026
In the Glimmer AST, `this.attrs.foo` has parts[0] === 'attrs' (this is
the receiver, not a part), so switching from original.startsWith('attrs.')
to parts[0] === 'attrs' matches upstream and correctly flags both bare
attrs.* and this.attrs.* — both are pre-Octane @ember/component patterns.
…roaden test coverage Add /components/ to the path gate regex to catch Octane co-located templates (app/components/foo.hbs) which the previous pattern missed (cf. ember-template-lint#1445). Add invalid test cases for attrs in attribute value, block helper, and hash pair positions, and for the co-located path pattern.
NullVoxPopuli
approved these changes
Apr 15, 2026
| @@ -1,5 +1,7 @@ | |||
| # ember/template-no-attrs-in-components | |||
|
|
|||
| > **HBS Only**: This rule applies to classic `.hbs` template files only (loose mode). It is not relevant for `gjs`/`gts` files (strict mode), where these patterns cannot occur. | |||
Contributor
There was a problem hiding this comment.
this is not hbs only
NullVoxPopuli
requested changes
Apr 15, 2026
…both' The rule applies in both HBS and GJS/GTS — classic @ember/component components can be authored in strict mode too, and their templates can still leak `this.attrs.*`. Regenerated docs to drop the incorrect "HBS Only" note.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
attrs.*andthis.attrs.*— both are pre-Octane args-leakage patterns from@ember/componenttemplateMode: 'loose'andoriginallyFrommetadataTest plan
{{attrs.foo}}in component template path → flagged{{this.attrs.foo}}in component template path → flagged{{attrs.foo}}in non-component template path → not flagged (path gate){{this.attrs.foo}}in non-component template path → not flagged (path gate)