Skip to content

Per-class resource locators are text-based, so const-folded templateUrl/styleUrls fall back to file-level resolution #456

Description

@Brooooooklyn

Split out of a Codex review finding on #455. Pre-existing — applies equally to the template locator merged in #449.

Symptom

The @ng/component HMR endpoint resolves a class's own templateUrl and styleUrl(s) by scanning the decorator text. The Rust extractor statically folds same-file constants and interpolated template literals; the text scan cannot.

const DIR = './themes'
@Component({ styleUrls: [`${DIR}/a.css`, SHARED_STYLE] })

Neither entry yields a string literal, so the per-class answer is "unknown" and the endpoint falls back to the file-level styleUrls union. In a single-component file that is harmless. In a multi-component file it reintroduces exactly the cross-class contamination #451 removed.

Current behavior is deliberate, not accidental

#455 makes the fallback explicit and distinguishes three states:

decorator state served
not locatable file-level fallback
locatable, no style field nothing
field present, no string literal file-level fallback

The third row is the const case. Falling back is strictly better than serving empty — a component keeps working — but it is not per-class correct.

Scope

This is not style-specific. extractTemplateUrlFor (from #449) has the same limitation, and falls back to templateUrls[0].

Suggested fix

Expose per-class resolved resources from the existing AST metadata extraction — extract_component_metadata_sync already returns templateUrl/styleUrls per class with constants folded — and have the endpoint consult that instead of re-scanning source text. That removes the text locators from the resolution path entirely rather than teaching them to fold constants.

Worth checking first how the endpoint would get that metadata cheaply: it currently calls extractComponentUrls per request, and componentMetadataCache exists but stores stripped source, not parsed metadata.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions