Skip to content

Fix/template no yield only filter comments#58

Closed
johanrd wants to merge 3 commits intomasterfrom
fix/template-no-yield-only-filter-comments
Closed

Fix/template no yield only filter comments#58
johanrd wants to merge 3 commits intomasterfrom
fix/template-no-yield-only-filter-comments

Conversation

@johanrd
Copy link
Copy Markdown
Owner

@johanrd johanrd commented Apr 24, 2026

Cowritten by claude:

Summary

  • template-no-yield-only flags yield-only templates via templateNodes.length === 1 && isYieldOnly(templateNodes[0]). That holds only while the parser strips template comments out of the body, which [email protected] happened to do.
  • Upstream [email protected] (NullVoxPopuli/ember-estree#31) started keeping MustacheCommentStatement nodes in the body (the native Glimmer AST shape). Under that parser a template like <template>{{! x }}{{yield}}</template> has a body of length 2 and is silently no longer flagged. This is the rule failure that blocks Update ember-eslint-parser to 0.11 ember-cli/eslint-plugin-ember#2735's CI.
  • Fix: filter comment + whitespace-only text nodes before the length check, via the same isEmptyNode helper that upstream ember-template-lint and the sibling rule template-no-bare-yield.js already use.

Why fix it here rather than in the parser / estree

[email protected]'s change is the correct AST: it matches the pure-hbs parser (ember-eslint-parser/hbs) and the native Glimmer AST, both of which have always kept comment nodes in the template body. Re-hiding those nodes at the parser layer would re-introduce the bug that ember-cli#2733 guards against ({{! eslint-disable-* }} directives would again be invisible to tooling that needs to see them). The semantic decision "should a comment-plus-yield template count as yield-only?" belongs to the rule.

Notes

  • template-no-bare-yield.js and template-no-yield-only.js are near-duplicate ports of ember-template-lint/lib/rules/no-yield-only.js; only the former had kept pace with upstream's empty-node filter. This closes that drift.
  • The filter is a no-op on the currently-pinned [email protected], so this is safe to land independently of Update ember-eslint-parser to 0.11 ember-cli/eslint-plugin-ember#2735 and paves the way for that PR's CI to go green once rebased.
  • This also fixes a latent bug the rule had on 0.10: <!-- html -->{{yield}} was not being flagged as yield-only; now it is.

Test plan

  • pnpm test tests/lib/rules/template-no-yield-only.js — 22 passed (18 original + 4 new assertions: {{!-- long --}}{{yield}} and <!-- x -->{{yield}} against both the gjs and hbs parsers)
  • npx prettier --check + npx eslint clean on both modified files
  • CI green

NullVoxPopuli and others added 3 commits April 24, 2026 14:25
The rule flagged yield-only templates by asserting
`templateNodes.length === 1 && isYieldOnly(templateNodes[0])`. That
works only while the parser strips template comments out of the body,
which ember-estree 0.4.2 happened to do. Upstream ember-estree 0.4.3
(#31) began keeping MustacheCommentStatement nodes in the body, so a
template like

    <template>{{! some comment }}{{yield}}</template>

now yields a body of length 2 and silently stops being flagged — which
is also why PR ember-cli#2735 (upgrade to ember-eslint-parser 0.11) fails this
rule's CI.

Ignoring comment and whitespace-only text nodes before the length check
aligns with:

- upstream ember-template-lint's `no-yield-only.js` (unchanged there
  since comments-in-body is the native Glimmer AST shape anyway)
- the sibling rule `template-no-bare-yield.js`, which already uses the
  same `isEmptyNode` filter

The fix is a no-op on the currently-pinned [email protected] and
fixes the rule under any parser version that preserves comment nodes in
the template body. The rule also now correctly catches yield-only
templates that contain HTML comments (`<!-- x -->{{yield}}`), which it
was silently missing before.
@github-actions
Copy link
Copy Markdown

🏎️ Benchmark Comparison

Benchmark Control (p50) Experiment (p50) Δ
🟢 js small 15.10 ms 13.99 ms -7.3%
js medium 7.10 ms 6.96 ms -1.9%
js large 2.79 ms 2.74 ms -2.0%
gjs small 1.24 ms 1.25 ms +0.9%
gjs medium 614.91 µs 614.75 µs -0.0%
gjs large 246.02 µs 245.37 µs -0.3%
gts small 1.23 ms 1.23 ms -0.3%
gts medium 619.10 µs 612.92 µs -1.0%
gts large 245.36 µs 244.16 µs -0.5%

🟢 faster · 🔴 slower · 🟠 slightly slower · ⚪ within 2%

Full mitata output
clk: ~3.04 GHz
cpu: AMD EPYC 7763 64-Core Processor
runtime: node 24.14.1 (x64-linux)

benchmark                   avg (min … max) p75 / p99    (min … top 1%)
------------------------------------------- -------------------------------
js small (control)            17.28 ms/iter  18.66 ms ▄   █                
                      (12.40 ms … 32.43 ms)  27.48 ms ███▅█▅              ▅
                    (  5.76 mb …  10.13 mb)   7.25 mb ██████▁▅▅▅▁▁▅▁▅▁▁▁▁██

js small (experiment)         14.59 ms/iter  15.19 ms  ▄ ▄█                
                      (12.74 ms … 20.61 ms)  18.60 ms  ████▅ ▅      ▅      
                    (  6.75 mb …   8.14 mb)   6.83 mb ████████▅██▁▅▁█▁▁▅▁▁▅

                             ┌                                            ┐
                             ╷  ┌───────────┬───┐                         ╷
          js small (control) ├──┤           │   ├─────────────────────────┤
                             ╵  └───────────┴───┘                         ╵
                              ╷ ┌───┬┐         ╷
       js small (experiment)  ├─┤   │├─────────┤
                              ╵ └───┴┘         ╵
                             └                                            ┘
                             12.40 ms           19.94 ms           27.48 ms

summary
  js small (experiment)
   1.18x faster than js small (control)

------------------------------------------- -------------------------------
js medium (control)            7.70 ms/iter   8.10 ms ▄█                   
                       (6.60 ms … 13.74 ms)  13.57 ms ██▅                  
                    (  2.53 mb …   4.69 mb)   3.55 mb ███▆▃█▅▂▁▃▂▁▂▁▁▁▂▂▂▁▂

js medium (experiment)         7.45 ms/iter   7.81 ms ▇█                   
                       (6.50 ms … 14.58 ms)  13.07 ms ██▃                  
                    (  2.60 mb …   4.38 mb)   3.55 mb ████▇█▄▅▁▂▁▂▁▁▁▁▁▁▁▁▃

                             ┌                                            ┐
                              ╷┌─────┬─┐                                  ╷
         js medium (control)  ├┤     │ ├──────────────────────────────────┤
                              ╵└─────┴─┘                                  ╵
                             ╷┌────┬─┐                                 ╷
      js medium (experiment) ├┤    │ ├─────────────────────────────────┤
                             ╵└────┴─┘                                 ╵
                             └                                            ┘
                             6.50 ms           10.03 ms            13.57 ms

summary
  js medium (experiment)
   1.03x faster than js medium (control)

------------------------------------------- -------------------------------
js large (control)             3.28 ms/iter   3.13 ms  █                   
                       (2.42 ms … 10.53 ms)   9.32 ms  █                   
                    (701.26 kb …   3.02 mb)   1.44 mb ▇█▄▃▃▂▂▁▁▁▂▁▁▁▁▁▁▁▁▁▁

js large (experiment)          3.07 ms/iter   2.88 ms  █                   
                        (2.55 ms … 7.60 ms)   6.44 ms ▅█                   
                    (190.88 kb …   2.51 mb)   1.43 mb ██▄▂▃▂▁▂▁▂▁▂▁▂▁▁▁▁▁▁▂

                             ┌                                            ┐
                             ╷ ┌───┬                                      ╷
          js large (control) ├─┤   │──────────────────────────────────────┤
                             ╵ └───┴                                      ╵
                              ┌──┬                     ╷
       js large (experiment)  │  │─────────────────────┤
                              └──┴                     ╵
                             └                                            ┘
                             2.42 ms            5.87 ms             9.32 ms

summary
  js large (experiment)
   1.07x faster than js large (control)

------------------------------------------- -------------------------------
gjs small (control)            1.38 ms/iter   1.32 ms █                    
                        (1.20 ms … 6.43 ms)   5.34 ms █                    
                    (283.50 kb …   1.66 mb)   1.06 mb ██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gjs small (experiment)         1.48 ms/iter   1.46 ms █                    
                        (1.20 ms … 7.16 ms)   5.79 ms █                    
                    (251.88 kb …   1.89 mb)   1.06 mb █▅▄▄▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ┌─┬                                      ╷
         gjs small (control) │ │──────────────────────────────────────┤
                             └─┴                                      ╵
                             ┌──┬                                         ╷
      gjs small (experiment) │  │─────────────────────────────────────────┤
                             └──┴                                         ╵
                             └                                            ┘
                             1.20 ms            3.49 ms             5.79 ms

summary
  gjs small (control)
   1.08x faster than gjs small (experiment)

------------------------------------------- -------------------------------
gjs medium (control)         663.31 µs/iter 629.67 µs █                    
                      (586.19 µs … 5.49 ms)   2.12 ms █▄                   
                    (292.89 kb …   1.28 mb) 542.21 kb ██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gjs medium (experiment)      660.05 µs/iter 628.45 µs  █                   
                      (584.58 µs … 5.43 ms)   1.30 ms ▂█                   
                    (246.01 kb …   1.26 mb) 541.42 kb ██▃▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷┌┬                                          ╷
        gjs medium (control) ├┤│──────────────────────────────────────────┤
                             ╵└┴                                          ╵
                             ╷┌┬                  ╷
     gjs medium (experiment) ├┤│──────────────────┤
                             ╵└┴                  ╵
                             └                                            ┘
                             584.58 µs           1.35 ms            2.12 ms

summary
  gjs medium (experiment)
   1x faster than gjs medium (control)

------------------------------------------- -------------------------------
gjs large (control)          273.27 µs/iter 262.77 µs █                    
                      (235.18 µs … 4.61 ms) 662.22 µs ██                   
                    (143.71 kb … 966.31 kb) 217.29 kb ██▆▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gjs large (experiment)       267.35 µs/iter 261.88 µs  █                   
                      (236.37 µs … 4.94 ms) 339.30 µs  ██                  
                    (215.70 kb … 808.47 kb) 216.38 kb ▆██▄▂▇▇▄▂▁▁▂▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷┌──┬                                        ╷
         gjs large (control) ├┤  │────────────────────────────────────────┤
                             ╵└──┴                                        ╵
                             ╷┌─┬       ╷
      gjs large (experiment) ├┤ │───────┤
                             ╵└─┴       ╵
                             └                                            ┘
                             235.18 µs         448.70 µs          662.22 µs

summary
  gjs large (experiment)
   1.02x faster than gjs large (control)

------------------------------------------- -------------------------------
gts small (control)            1.33 ms/iter   1.26 ms █                    
                        (1.20 ms … 6.53 ms)   5.25 ms █                    
                    (312.16 kb …   1.82 mb)   1.06 mb █▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gts small (experiment)         1.32 ms/iter   1.25 ms █                    
                        (1.20 ms … 6.04 ms)   4.93 ms █                    
                    (536.59 kb …   1.60 mb)   1.05 mb █▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ┌─┬                                          ╷
         gts small (control) │ │──────────────────────────────────────────┤
                             └─┴                                          ╵
                             ┌┬                                       ╷
      gts small (experiment) ││───────────────────────────────────────┤
                             └┴                                       ╵
                             └                                            ┘
                             1.20 ms            3.22 ms             5.25 ms

summary
  gts small (experiment)
   1.01x faster than gts small (control)

------------------------------------------- -------------------------------
gts medium (control)         658.60 µs/iter 633.10 µs  █                   
                      (590.03 µs … 5.43 ms)   1.05 ms ▄█▇                  
                    (107.58 kb …   1.04 mb) 540.75 kb ███▄▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gts medium (experiment)      656.36 µs/iter 626.19 µs ▅█                   
                      (584.55 µs … 5.42 ms)   1.68 ms ██                   
                    (487.70 kb …   1.35 mb) 541.32 kb ██▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷┌─┬               ╷
        gts medium (control) ├┤ │───────────────┤
                             ╵└─┴               ╵
                             ╷┌─┬                                         ╷
     gts medium (experiment) ├┤ │─────────────────────────────────────────┤
                             ╵└─┴                                         ╵
                             └                                            ┘
                             584.55 µs           1.13 ms            1.68 ms

summary
  gts medium (experiment)
   1x faster than gts medium (control)

------------------------------------------- -------------------------------
gts large (control)          271.49 µs/iter 261.13 µs █▅                   
                      (234.10 µs … 4.59 ms) 567.55 µs ██▅                  
                    (216.09 kb … 957.78 kb) 216.97 kb ███▃▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gts large (experiment)       268.99 µs/iter 261.52 µs ▃█                   
                      (235.60 µs … 5.01 ms) 434.25 µs ██ ▄                 
                    ( 16.59 kb … 739.07 kb) 216.41 kb ██▅█▃▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷┌───┬                                       ╷
         gts large (control) ├┤   │───────────────────────────────────────┤
                             ╵└───┴                                       ╵
                             ╷┌───┬                     ╷
      gts large (experiment) ├┤   │─────────────────────┤
                             ╵└───┴                     ╵
                             └                                            ┘
                             234.10 µs         400.82 µs          567.55 µs

summary
  gts large (experiment)
   1.01x faster than gts large (control)

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@johanrd johanrd closed this Apr 24, 2026
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.

3 participants