Open
Conversation
📊 Package size report -3.47%↓
🤖 This report was automatically generated by pkg-size-action |
0eea75a to
2b7d50e
Compare
This was referenced Apr 16, 2026
…ract tests
Split into three files by concern:
- parser-escape-test.ts: backslash escape sequences (\{{, \\{{, \\\{{)
in top-level text, elements, attributes, and unclosed cases.
- parser-whitespace-test.ts: tilde stripping and standalone detection.
- parser-error-test.ts: inputs that must be rejected ({{}}}, {{~}}, {{@}}, etc).
parser-node-test.ts is unchanged.
2b7d50e to
8369d3f
Compare
Replaces both @handlebars/parser (Jison) and simple-html-tokenizer with a single left-to-right indexOf-based scanner that builds ASTv1 directly. No tokenizer pipeline, no intermediate representation, one pass. - parser.ts: 2507-line unified scanner, exported as unifiedPreprocess() - tokenizer-event-handlers.ts: simplified to delegate to the unified scanner - handlebars-node-visitors.ts: removed (logic absorbed into parser.ts) - @handlebars/parser: package deleted entirely - bench.mjs: 3-way comparison bench (Jison vs unified, retained for investigation) - CI/config: updated to remove @handlebars/parser references, add prettier snapshot update step for error-message differences All existing tests pass. Escape handling matches Jison (backslash counting, emu-state content merging). Error messages aligned where ember tests check specific text (Expecting 'ID').
Adds _precompileJSONWithPhaseTiming to @glimmer/compiler for benchmarking. Exposes normalizeAST (the ASTv1→ASTv2 part of normalize without re-parse) so phases can be measured independently. Expose the timing function through ember-template-compiler/minimal.ts (real ESM entry). Findings (bench-phases.mjs): on real-world templates, normalize is 54% of compile time and pass0 is only 11% — opposite of what code volume suggested. The ASTv1→ASTv2 transform is the next target, not Pass0.
…00, extra-large ~25000) Route templates in real apps are nowhere near 25 chars. The previous size ladder (25 → 3500) didn't stress the compile path enough to surface the O(n²) normalize behavior that the newline-cache fix eliminates, nor the IDE-case scaling of Jison. At realistic sizes the deltas become concrete: IDE (parse-only) Jison unified-1pass speedup small (462c) 0.22ms 0.06ms 3.4× medium (1494c) 0.69ms 0.17ms 4.1× large (4482c) 2.45ms 0.57ms 4.3× extra-large(25398c) 24.73ms 3.15ms 7.8× Full build Jison unified-1pass speedup extra-large(25398c) 93.32ms 25.94ms 3.6× Jison's per-char cost roughly doubles from medium to extra-large (0.46 → 0.97 μs/char), while unified-1pass holds steady at ~0.12 μs/char. Route templates like the one the user was just inspecting (~98k chars) will see the biggest impact.
b5b1a77 to
a27b008
Compare
callParts() was normalizing all parameters twice — once to calculate paramLoc (line 277), then again for the actual positional builder (line 282). Reuse the already-computed paramList instead. Impact: normalize phase 12-22% faster (measured via bench-phases.mjs on dev build, confirmed on prod build). End-to-end precompile ~6% faster on large templates.
element.attributes was iterated twice — once filtering for non-@ attrs, once for @-prefixed args. Combined into a single loop. Minor win (~5% normalize improvement on medium templates) but clean code: single allocation, single pass.
…vs args)" This reverts commit 7148a04.
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.
Unified single-pass HTML+HBS parser for
@glimmer/syntaxReplaces both
@handlebars/parser(Jison) andsimple-html-tokenizerwith a single left-to-rightindexOf-based scanner that builds ASTv1 directly — no tokenizer pipeline, no intermediate representation, one pass.Builds on the index-based cursor parser from #13, which replaces only the HBS layer (Jison → recursive descent) while keeping
simple-html-tokenizer. This PR goes further and replaces the HTML layer too.Exported as
unifiedPreprocess()alongside the existingpreprocess(). All tests pass.Benchmark (
pnpm bench:precompile)Apple M1 Max, Node 24.14, prod dist.
The index-based cursor parser (#13) replaces Jison's HBS layer only. This PR extends that by also replacing
simple-html-tokenizer, yielding a further ~2× on parse. End-to-end precompile is 1.4× faster than main.Reproduce:
pnpm build && pnpm bench:precompile, compare branches.Exploration tooling (also included)
Per-phase timing instrumentation used to investigate where compile time goes after parse is no longer the bottleneck:
_precompileJSONWithPhaseTiming— instrumentedprecompileJSONreturning{timings: {parse, normalize, pass0, pass2, stringify, total}}.normalizeAST— factored out ofnormalize()so you can bench normalize without re-parsing.bench-phases.mjs— per-phase benchmark at realistic sizes.This tooling found the
hbsPosForO(n²) hotspot (~28% self-time at large sizes), fixed separately in emberjs#21314. Also found the double-normalization incallParts(), extracted as johanrd/ember.js#18.