Skip to content

Commit 22fda69

Browse files
committed
fix(class-metadata): emit type: undefined for ctorParam annotations without a runtime value
Fixes #563. `setClassMetadata` ctorParams emitted the annotation's name even when the type has no value-space symbol — interfaces, type aliases, class type parameters, `import type` bindings — producing a `ReferenceError` when the metadata thunk evaluates. ngtsc's `typeToValue` (`type_to_value.ts`) marks these `TypeValueReferenceKind.UNAVAILABLE` and `ctorParameterToMetadata` emits `LiteralExpr(undefined)`. OXC compiles single files, matching upstream's `experimental-local` compilation (the mode the e2e comparison harness uses). In local mode `typeToValue` resolves only the declaration kinds visible in the file: `TypeParameter`, `TypeAliasDeclaration`, and `InterfaceDeclaration` are UNAVAILABLE; everything else emits as written under an upstream `/* @ts-ignore */` — const enums, vars, functions, bare namespace names, missing members (`ns.Missing`), even undeclared names. Verified against real ngtsc 22.2.1 output in local mode for every case. Reworked `build_param_type_expression` to mirror that flow: - `T | null` narrows to `T` first (`getConstructorParameters`); the narrowed node must be a bare `TSTypeReference` — parenthesized, union, `typeof`, `this`, and primitive annotations are UNAVAILABLE (previously `resolve_di_token_type` unwrapped them). - The DI dependency is no longer consulted; upstream derives `type:` purely from the annotation. - A bare class type parameter (`x: T`) is UNAVAILABLE; `T.Inner` emits — its member symbol has no type-only declaration. - `import type` / `import { type X }` are UNAVAILABLE. A bare namespace or `import =` alias reference (`x: ns`) is UNAVAILABLE for namespace imports but emits for `import =`. `ImportInfo` gained `is_default_import` to distinguish `import Foo from 'm'` (emits the local name — upstream's LOCAL + `defaultImportStatement`) from `import { default as Foo }` (emits `i1.default`, the IMPORTED path). - New `LocalDecls` records interface/type-alias names and namespace bodies recursively (unwrapping `export`, hoisting `declare global`), so `ns.Interface` resolves UNAVAILABLE while the merged `interface I` + `namespace I` symbol emits — its valueDeclaration is the namespace. Import elision keeps a default import when a decorated constructor's parameter annotation references it bare — metadata emits the local name, so eliding the import would leave `type: Foo` dangling. `StringConsts` gained a `program()` accessor so the metadata builder can scan the file's declarations. e2e: the three `ctorParams` metadataDiffs entries in known-differences.ts are removed — the emitted metadata now matches ngtsc.
1 parent f1d010d commit 22fda69

6 files changed

Lines changed: 588 additions & 139 deletions

File tree

0 commit comments

Comments
 (0)