Skip to content

fix(directive): emit a dynamic host attribute value as written, like ngtsc - #639

Merged
Brooooooklyn merged 4 commits into
voidzero-dev:mainfrom
edbzn:fix/transform-compile-errors
Oct 27, 2026
Merged

Brooooooklyn merged 4 commits into
voidzero-dev:mainfrom
edbzn:fix/transform-compile-errors

Conversation

@edbzn

@edbzn edbzn commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

Fixes #627 (case 1). Cases 2 and 3 in the issue are left unchanged on purpose. The issue explains why.

Problem

ngtsc's evaluateHostExpressionBindings (compiler-cli/src/ngtsc/annotations/directive/src/shared.ts) turns a host value it can't evaluate (DynamicValue) into WrappedNodeExpr(value.node). parseHostBindings emits that expression for a plain attribute (hostAttrs: ["test", test]). oxc stored host attribute values as strings and reported an error. A value computed from an import got the "imported from another module" error instead, with or without resolveImportedValues.

Fix

  • evaluate_host_metadata returns a HostValue for each entry: a string, or the expression ngtsc would emit. For a plain attribute, a dynamic value (an unknown name, a call, a function expression, or a value computed from an import) becomes its expression. The expression comes from Prop::origin, in the form it can be written where the metadata is compiled.
    • Imports count as dynamic here because ngtsc's local compilation mode doesn't read the other file either. Full mode would fold an imported string constant to a literal. The runtime attribute is the same.
  • The component HostMetadata.attributes holds OutputExpressions, like the directive's R3HostMetadata.attributes already does. Full emit and partial emit (host: { attributes: { role: make() } }) both use them.
  • These cases still report errors:
    • [prop], (event), class and style keep ngtsc's "... binding must be string" errors, or the import error.
    • An attribute whose expression can't be written where the metadata is compiled is still an error. That covers a value that uses the parameters of a helper the metadata calls, and an export of another module reached through { ...ns }.

Checks

  • host_metadata_evaluation_test:
    • dynamic_value_of_a_plain_attribute now asserts the emitted hostAttrs. It covers make(), an unknown name, a spread const, an import, and the ngtsc spec input. It used to assert the error.
    • New: dynamic_value_of_a_plain_attribute_partial and dynamic_value_of_a_plain_attribute_out_of_scope.
    • host_that_depends_on_an_import no longer expects an error for { role: SHARED }.
  • cross_file_values_test::dynamic_host_attribute_from_an_unreadable_import ports ngtsc_spec.ts "should accept dynamic host attribute bindings" with resolveImportedValues.
  • cargo test -p oxc_angular_compiler --all-features: 3519 passed, 0 failed, 1 ignored.
  • cargo fmt is clean. cargo clippy -p oxc_angular_compiler --all-features reports no warnings on the changed lines.

🤖 Generated with Claude Code

…ngtsc

ngtsc wraps a host value it can't evaluate in a WrappedNodeExpr and emits it
in hostAttrs for a plain attribute; oxc rejected it. Values computed from an
import are treated the same way, as ngtsc's local compilation mode does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brooooooklyn and others added 2 commits October 27, 2026 14:27
…etadataSync

Host attribute values are now `OutputExpression`s, so the napi crate no
longer built (`to_string` on an expression). Report a static value as its
string, as before, and a dynamic one (`role: foo.bar()`) as the expression
`hostAttrs` emits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Brooooooklyn

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-27T06:55:10.487431Z
We couldn’t complete this review. Comment @codex review to try again.
fab2c50 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

An unknown error occurred
ℹ️ 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".

… ngtsc

ngtsc emits a host attribute's `DynamicValue` as written, including a
value computed from an import (`foo.bar()`, `SHARED + '!'`, `ns.foo.bar`).
An import named itself (`SHARED`, `ns.SHARED`, `const R = SHARED`) is a
`Reference` instead, which ngtsc rejects in full and local compilation
mode alike when the other file has no readable value ("found unparseable
value"). Keep reporting it as imported, as before this branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Brooooooklyn

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

An unknown error occurred
ℹ️ 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".

@Brooooooklyn

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

An unknown error occurred
ℹ️ 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".

@Brooooooklyn
Brooooooklyn merged commit 420ebf6 into voidzero-dev:main Oct 27, 2026
9 checks passed
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.

Dynamic host attribute values are rejected (and two local-compilation-only transform cases)

2 participants