Repository navigation
feat(transform): add ngtsc's implicit signal debugName - #658
Conversation
Port ngtsc's `signalMetadataTransform`
(compiler-cli transform/src/implicit_signal_debug_name_transform.ts,
chunk-G5LDCSK3.js:1970-2179). NgCompiler always adds it to the `before`
emit transforms (chunk-HIDZX47I.js:4547), in full and partial mode, for
every emitted file.
`const x = signal(0)`, `x = input()` fields and `this.x = computed(...)`
statements now get an ngDevMode `debugName` named after the binding, for
signal, computed, linkedSignal, input, model, the signal queries,
effect, afterRenderEffect, resource and httpResource. The callee must be
a named import from its `@angular/*` package, under the same local name.
Options objects get `...(ngDevMode ? { debugName } : {})` as their first
property; a missing options argument becomes a spread argument.
Upstream edits the nodes, so text printed again elsewhere is named in
every copy: decorator arguments in the definitions and
`ɵsetClassMetadata` (`make_raw_source`), the JIT `__decorate` and
`propDecorators` texts of a `jit: true` class, a `@Service` factory and a
hoisted statement. Each edit keeps the span of the declaration it names;
a slice takes the edits of the declarations inside it, and the file
drops the edits in text another edit removes.
Like upstream: `signal?.(0)` is a call; `(this.x) = signal()` has a
parenthesized target and is skipped; a computed key's name keeps the
comments inside its brackets; and `input()` fields of a jit-forced
class keep no name, because the JIT `signalInputsTransform`
(initializer_api_transforms/input_function.ts) rebuilds them with a
string name first, so `node.name.getText()` throws.
The pass runs in transform_angular_file for files without an Angular
decorator too. The Vite plugin now lets a decorator-less file through
when it calls one of these APIs from Angular (not in JIT mode, which has
no such transform).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7e6dc08237
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…e pass The fast path for files without an Angular decorator matched only `signal(`-like calls, so `signal?.(0)` and `signal /* c */ (0)` skipped the transform the Rust pass handles. Match the API name alone: the file must still import from `@angular/core` or `@angular/common`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
Part of #623 (the
debugNamerow, listed as known inknown-differences.ts).This ports ngtsc's
signalMetadataTransform(implicit_signal_debug_name_transform.ts). Calls tosignal,computed,linkedSignal,input,model, the signal queries,effect,afterRenderEffect,resourceandhttpResourcenow get an ngDevModedebugNamenamed after their binding. This works in full and partial mode, and in files without an Angular decorator too.Upstream changes the AST nodes themselves. So any text that gets printed a second time also gets the name:
Design note
make_raw_sourceand the other places that print decorator text again get the edits through a thread-local (FileDebugNamesinsignal_debug_name.rs). It is keyed by the source text's address and cleared on drop. The other way was to pass the edits through about 120 converter call sites. If you'd rather have them passed in explicitly, I can change it.Before / after
Input:
Before (broken JS, the edit landed in deleted decorator text):
After (same as ngtsc, in ɵcmp and in setClassMetadata):
Other shapes, matching ngtsc:
ngtsc parity cases checked (compiler-cli 22.2.3)
@Componentproviders with auseFactoryblock,@InjectableuseFactory,@NgModuleproviders,@Input({ transform }), a class expression inside providers, and@Servicefactory. Checked in full and partial mode.jit: truecomponent with providers,input(),input.required(),@Input() x = input(),model(),viewChild(.., { read }),signal(), and a namelessexport defaultjit class.signal?.(0),(this.b) = signal(1),(this).c = signal(2), and computed keys with block and line comments.Checks
cargo test --all-features: 3610 passed, 0 failed.decorator_arguments_are_named_in_every_copy,jit_forced_class,service_factory_is_named,call_and_target_shapes) fail on the previous source and pass now.build-test: OK. vitest: 21 files, 400 tests passed.tsc --noEmit: OK. oxfmt and oxlint on the changed TS files: clean.--fixtures: 51 matched, 0 mismatched, 0 errors.🤖 Generated with Claude Code