Skip to content

BUGFIX: template-no-invalid-aria-attributes — accept "undefined" as valid aria-orientation token#29

Closed
johanrd wants to merge 2 commits intomasterfrom
fix/aria-orientation-undefined-token
Closed

BUGFIX: template-no-invalid-aria-attributes — accept "undefined" as valid aria-orientation token#29
johanrd wants to merge 2 commits intomasterfrom
fix/aria-orientation-undefined-token

Conversation

@johanrd
Copy link
Copy Markdown
Owner

@johanrd johanrd commented Apr 21, 2026

Premise

  • Per aria-query 5.3.2, aria-orientation is defined as { type: 'token', values: ['vertical', 'undefined', 'horizontal'] }. The literal string \"undefined\" is an explicit, valid token value.
  • The rule validates token-typed attributes by checking membership in attrDef.values.
  • Before this change, isValidAriaValue short-circuited on value === 'undefined' and returned Boolean(attrDef.allowundefined) before reaching the token check.
  • aria-query sets allowundefined: false on aria-orientation, so the valid literal token \"undefined\" was rejected by the short-circuit.

Conclusion

Reorder the checks so that when the attribute is a token/tokenlist and its values array explicitly includes 'undefined', we accept it without consulting allowundefined. The allowundefined shortcut still applies to every other attribute where \"undefined\" is a general escape hatch (e.g. aria-expanded, aria-pressed), so no existing valid behavior regresses.

Changes

  • lib/rules/template-no-invalid-aria-attributes.js — add the token-list precheck ahead of the allowundefined shortcut.
  • tests/lib/rules/template-no-invalid-aria-attributes.js — regression tests for aria-orientation in both <template> and hbs parsers:
    • valid: aria-orientation=\"undefined\"
    • valid: aria-orientation=\"horizontal\"
    • invalid: aria-orientation=\"sideways\"

References

Test plan

  • npx vitest run tests/lib/rules/template-no-invalid-aria-attributes.js — 74 tests pass.
  • npx prettier --write on both touched files — no formatting changes.
  • After merge, rebase audit/phase3/aria-props onto master and confirm the B9 divergence fixture passes.

…d token for aria-orientation

Per aria-query 5.3.2, `aria-orientation` has `type: 'token'` with
`values: ['vertical', 'undefined', 'horizontal']` — i.e. the literal
string "undefined" is an explicit, valid token.

Our previous implementation short-circuited on `value === 'undefined'`
by returning `Boolean(attrDef.allowundefined)` before the token check.
Because `aria-orientation` carries `allowundefined: false` in aria-query,
the valid token "undefined" was incorrectly rejected.

Fix: before applying the generic `allowundefined` shortcut, check
whether the attribute is a `token`/`tokenlist` whose `values` array
explicitly includes `'undefined'`. If so, the value is valid regardless
of `allowundefined`.

Regression tests cover the valid (`undefined`, `horizontal`) and invalid
(`sideways`) cases for `aria-orientation`, in both `<template>` and hbs
parsers.

Reference: audit finding B9 (tests/audit/aria-props/peer-parity.js on
audit/phase3/aria-props); PR #28 backlog item F1.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 21, 2026

🏎️ Benchmark Comparison

Benchmark Control (p50) Experiment (p50) Δ
🟢 js small 15.77 ms 15.03 ms -4.7%
js medium 7.62 ms 7.55 ms -1.0%
🟢 js large 2.98 ms 2.85 ms -4.5%
🟢 gjs small 1.32 ms 1.25 ms -4.8%
gjs medium 629.12 µs 621.21 µs -1.3%
gjs large 250.28 µs 249.25 µs -0.4%
gts small 1.24 ms 1.25 ms +0.3%
gts medium 629.81 µs 623.30 µs -1.0%
gts large 248.68 µs 247.09 µs -0.6%

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

Full mitata output
clk: ~3.09 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)            18.45 ms/iter  20.10 ms █ █                  
                      (12.86 ms … 31.98 ms)  29.88 ms █ █▅           ▅     
                    (  5.00 mb …  10.41 mb)   7.29 mb ████▅███▁▅▁▁▁▁▁█▁▁▅▅█

js small (experiment)         15.90 ms/iter  16.44 ms  ▃█                  
                      (13.83 ms … 22.41 ms)  21.99 ms  ██                  
                    (  6.33 mb …   8.82 mb)   6.84 mb ▆███▆▆█▆▄▄▄▄▄▁▁▁▁▁▁▄▄

                             ┌                                            ┐
                             ╷   ┌──────────┬───┐                         ╷
          js small (control) ├───┤          │   ├─────────────────────────┤
                             ╵   └──────────┴───┘                         ╵
                                ╷┌───┬┐              ╷
       js small (experiment)    ├┤   │├──────────────┤
                                ╵└───┴┘              ╵
                             └                                            ┘
                             12.86 ms           21.37 ms           29.88 ms

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

------------------------------------------- -------------------------------
js medium (control)            8.42 ms/iter   8.82 ms  █                   
                       (7.03 ms … 16.15 ms)  15.96 ms ██▃                  
                    (  2.66 mb …   4.34 mb)   3.56 mb ███▅▆▆▁▄▁▁▄▁▂▁▂▂▁▁▁▁▂

js medium (experiment)         8.17 ms/iter   8.63 ms █▂                   
                       (7.00 ms … 15.11 ms)  14.12 ms ██▆                  
                    (  1.43 mb …   5.59 mb)   3.52 mb ███▆▄▄▅▅▃▄▂▂▁▁▁▁▁▁▂▁▂

                             ┌                                            ┐
                             ╷┌─────┬─┐                                   ╷
         js medium (control) ├┤     │ ├───────────────────────────────────┤
                             ╵└─────┴─┘                                   ╵
                             ╷┌────┬─┐                           ╷
      js medium (experiment) ├┤    │ ├───────────────────────────┤
                             ╵└────┴─┘                           ╵
                             └                                            ┘
                             7.00 ms           11.48 ms            15.96 ms

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

------------------------------------------- -------------------------------
js large (control)             3.30 ms/iter   3.17 ms  █                   
                        (2.75 ms … 7.43 ms)   6.39 ms  █▄                  
                    (736.57 kb …   2.24 mb)   1.43 mb ▇██▃▂▂▄▂▁▂▁▁▂▁▁▁▁▃▁▁▁

js large (experiment)          3.43 ms/iter   3.27 ms ▅█                   
                        (2.61 ms … 9.70 ms)   8.83 ms ██                   
                    (130.94 kb …   3.56 mb)   1.43 mb ██▇▃▂▄▃▂▂▁▁▂▁▂▁▂▁▁▂▂▁

                             ┌                                            ┐
                              ╷┌──┬                     ╷
          js large (control)  ├┤  │─────────────────────┤
                              ╵└──┴                     ╵
                             ╷┌────┬                                      ╷
       js large (experiment) ├┤    │──────────────────────────────────────┤
                             ╵└────┴                                      ╵
                             └                                            ┘
                             2.61 ms            5.72 ms             8.83 ms

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

------------------------------------------- -------------------------------
gjs small (control)            1.46 ms/iter   1.41 ms █                    
                        (1.22 ms … 7.30 ms)   6.19 ms █▆                   
                    (220.48 kb …   1.91 mb)   1.06 mb ██▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gjs small (experiment)         1.39 ms/iter   1.30 ms █                    
                        (1.20 ms … 6.72 ms)   5.70 ms █                    
                    (224.19 kb …   1.59 mb)   1.06 mb █▆▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷┌┬                                          ╷
         gjs small (control) ├┤│──────────────────────────────────────────┤
                             ╵└┴                                          ╵
                             ┌─┬                                      ╷
      gjs small (experiment) │ │──────────────────────────────────────┤
                             └─┴                                      ╵
                             └                                            ┘
                             1.20 ms            3.70 ms             6.19 ms

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

------------------------------------------- -------------------------------
gjs medium (control)         684.46 µs/iter 650.92 µs  █                   
                      (591.71 µs … 6.00 ms)   1.44 ms  █                   
                    ( 85.66 kb …   1.12 mb) 541.50 kb ██▆▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gjs medium (experiment)      673.95 µs/iter 642.44 µs  █                   
                      (585.54 µs … 5.72 ms)   1.35 ms  █                   
                    (144.61 kb … 985.52 kb) 540.94 kb ███▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷ ┌──┬                                       ╷
        gjs medium (control) ├─┤  │───────────────────────────────────────┤
                             ╵ └──┴                                       ╵
                             ╷┌───┬                                  ╷
     gjs medium (experiment) ├┤   │──────────────────────────────────┤
                             ╵└───┴                                  ╵
                             └                                            ┘
                             585.54 µs           1.01 ms            1.44 ms

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

------------------------------------------- -------------------------------
gjs large (control)          278.46 µs/iter 265.44 µs  █                   
                      (235.54 µs … 5.23 ms) 476.76 µs ██▂                  
                    (216.10 kb … 836.33 kb) 217.66 kb ████▅▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gjs large (experiment)       275.57 µs/iter 265.87 µs  █                   
                      (236.26 µs … 5.37 ms) 397.91 µs ▂██ ▂                
                    (125.55 kb … 739.03 kb) 216.49 kb ███▅█▇▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷┌──────┬                                    ╷
         gjs large (control) ├┤      │────────────────────────────────────┤
                             ╵└──────┴                                    ╵
                             ╷┌─────┬                      ╷
      gjs large (experiment) ├┤     │──────────────────────┤
                             ╵└─────┴                      ╵
                             └                                            ┘
                             235.54 µs         356.15 µs          476.76 µs

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

------------------------------------------- -------------------------------
gts small (control)            1.34 ms/iter   1.27 ms █                    
                        (1.20 ms … 6.71 ms)   4.57 ms █                    
                    (417.58 kb …   1.72 mb)   1.06 mb █▅▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gts small (experiment)         1.34 ms/iter   1.27 ms █                    
                        (1.20 ms … 6.45 ms)   4.34 ms █                    
                    (164.18 kb …   1.55 mb)   1.05 mb █▆▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

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

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

------------------------------------------- -------------------------------
gts medium (control)         679.10 µs/iter 649.70 µs ▆█                   
                      (590.99 µs … 5.66 ms)   2.02 ms ██                   
                    (233.25 kb …   1.07 mb) 541.61 kb ██▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

gts medium (experiment)      673.39 µs/iter 644.53 µs  █                   
                      (588.09 µs … 5.81 ms)   1.30 ms  █▂                  
                    (106.59 kb …   1.04 mb) 539.82 kb ███▃▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷┌─┬                                         ╷
        gts medium (control) ├┤ │─────────────────────────────────────────┤
                             ╵└─┴                                         ╵
                             ╷┌─┬                  ╷
     gts medium (experiment) ├┤ │──────────────────┤
                             ╵└─┴                  ╵
                             └                                            ┘
                             588.09 µs           1.30 ms            2.02 ms

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

------------------------------------------- -------------------------------
gts large (control)          274.85 µs/iter 265.52 µs  █                   
                      (235.66 µs … 5.72 ms) 378.91 µs  █▇                  
                    (216.09 kb … 770.34 kb) 217.18 kb ▄██▅█▆▄▂▂▁▁▁▁▁▁▁▁▁▁▁▁

gts large (experiment)       277.24 µs/iter 265.04 µs  █                   
                      (236.23 µs … 5.98 ms) 356.48 µs  ██                  
                    (215.70 kb … 728.55 kb) 216.87 kb ▇██▅▄█▇▄▂▂▁▁▁▁▁▁▁▁▁▁▁

                             ┌                                            ┐
                             ╷ ┌─────────┬                                ╷
         gts large (control) ├─┤         │────────────────────────────────┤
                             ╵ └─────────┴                                ╵
                             ╷ ┌──────────┬                        ╷
      gts large (experiment) ├─┤          │────────────────────────┤
                             ╵ └──────────┴                        ╵
                             └                                            ┘
                             235.66 µs         307.28 µs          378.91 µs

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

@johanrd
Copy link
Copy Markdown
Owner Author

johanrd commented Apr 21, 2026

Moved upstream to ember-cli#2723. See that PR for ongoing review.

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

1 participant