fix(decorator): fold ${const} template literals in metadata fields#300
Merged
Merged
Conversation
…286) Angular's partial evaluator constant-folds template literals whose `${...}` interpolations reference same-file string `const`s. OXC was bailing on any TemplateLiteral with non-empty `expressions`, so `template:`/`selector:` silently dropped (AOT skipped the component) and JIT `templateUrl`/`styleUrl`/ `styleUrls` ignored the same shapes. Resolve interpolations recursively through the existing `StringConsts` map (with iterative fixed-point so chained consts fold) and share the resolver between AOT extraction and JIT decorator rewriting so both accept identical metadata shapes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 63a84e9. Configure here.
Per Cursor Bugbot review: the local `extract_string_value` and `resolve_template_literal` in `component/decorator.rs` are byte-for-byte equivalent to the ones exported as `pub(crate)` from `directive/decorator.rs`. Reuse the directive copies and funnel `extract_string_array` elements through the same resolver so a future fix doesn't risk drifting between modules. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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
template:/selector:with${const}template-literal interpolation were silently dropped (AOT skipped the component, noɵcmp; or emittedselectors:[["ng-component"]]).extract_string_valueincomponent/decorator.rsanddirective/decorator.rsnow recursively folds${...}expressions through the existingStringConstsmap; nested/chained consts resolve via an iterative fixed-point incollect_string_consts.build_jit_decorator_textshares the same resolver, sotemplateUrl/styleUrl/styleUrlsaccept the same identifier and template-literal shapes as AOT (closes the AOT/JIT asymmetry surfaced by/codex:adversarial-review).Root cause
extract_string_valuerejected anyTemplateLiteralwith non-emptyexpressions, sotemplate: `<button class="${twBtn}">x</button>`returnedNoneand the whole@Componentdecorator was treated as un-extractable.StringConstsfrom #271 was only consulted for bare identifier references.Changes
crates/oxc_angular_compiler/src/directive/decorator.rs: addresolve_template_literal(interleaves quasis with partial-evaluated${...}expressions); thread&'a Allocatorthroughextract_string_value; iterative fixed-point incollect_string_constsfor chained consts; exportextract_string_valueaspub(crate).crates/oxc_angular_compiler/src/component/decorator.rs: mirrorresolve_template_literal; thread allocator throughextract_string_valueandextract_string_array(which also accepts[CONST_STR]and[`${CONST}`]array elements).crates/oxc_angular_compiler/src/component/transform.rs: collectstring_constsin the JIT path and feedbuild_jit_decorator_text, which now resolves URL values through the sharedextract_string_valuesotemplateUrl: `${DIR}/x.html`andtemplateUrl: PATH_CONSTfold in JIT too.crates/oxc_angular_compiler/src/directive/mod.rs:pub(crate) use decorator::extract_string_value.napi/angular-compiler/src/lib.rs: pass allocator tocollect_string_constsinextract_component_urls_syncandextract_metadata_sync.Test plan
cargo test -p oxc_angular_compiler— 2454 passed, 0 failed, 1 ignored (pre-existing).tests/integration_test.rscovering AOTtemplate:/selector:interpolation in@Componentand@Directive, multiple interpolations, chained consts (const TAG = \${PREFIX}-x`),styles:array elements, graceful fallback on unresolved identifiers, plus JITtemplateUrl/styleUrl/styleUrls` for both template-literal and identifier shapes.cargo build --all-targets— clean (only pre-existing missing-docs warnings)./codex:adversarial-review— initial pass flagged the JIT gap, which this PR also closes; re-verified with the full extended fix.🤖 Generated with Claude Code
Note
Medium Risk
Touches core decorator metadata extraction and JIT decorator rewriting; incorrect folding could change selectors, templates, or resource paths, though behavior is constrained to statically resolvable same-file consts with tests covering main shapes.
Overview
Fixes #286: decorator metadata that used
`${const}`template literals (or const identifiers) in fields liketemplate,selector, andstyleswere treated as unextractable, so AOT could skipɵɵdefineComponentor emit wrong selectors.Shared partial evaluation in
directive/decorator.rs:extract_string_valuenow folds template literals viaresolve_template_literal, andcollect_string_conststakes an allocator and resolves chained top-levelconstvalues in a fixed-point loop. Component and directive metadata parsing route string fields andstyles/styleUrlsarray elements through this helper instead of local duplicate logic.JIT parity:
build_jit_decorator_textcollectsstring_constsand resolvestemplateUrl,styleUrl, andstyleUrlsthe same way, soangular:jit:*:file;imports get folded paths. NAPI call sites pass the allocator intocollect_string_consts.Eleven integration tests cover AOT/JIT folding, chained consts, and graceful drop when interpolations cannot be resolved.
Reviewed by Cursor Bugbot for commit c3bb670. Bugbot is set up for automated code reviews on this repo. Configure here.