fix(metadata): `setClassMetadata` names `Inject` / `Optional` / tokens whose imports OXC removed (ReferenceError under TestBed overrides)
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 3/5
- Geschätzter Aufwand
- 1-2 Tage
- Anfängerfreundlichkeit
- 76/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- angular, rust, typescript
- Bereich
- compilers
Rechercherichtung
Start in crates/oxc_angular_compiler/src/component/import_elision.rs, then trace class_metadata/builders.rs, especially the constructor-parameter import collection and metadata builder named in the issue. Run the supplied TestBed override reproduction with metadata enabled; done means the generated module retains imports needed by ɵsetClassMetadata and the override no longer raises ReferenceError.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
OXC removes the imports of Angular's constructor parameter decorators (Inject, Optional, Self, SkipSelf, Host, Attribute) and of tokens used only inside @Inject(...). The factory doesn't need them (it uses i0. / i1. namespace imports). But ɵsetClassMetadata, which is emitted by default, still names them as bare identifiers in its ctorParameters callback. Those names no longer exist in the module.
The callback is lazy, so a normal app works. It throws as soon as Angular reads ctorParameters, for example when TestBed.overrideComponent / overrideDirective / overridePipe / overrideModule recompiles the class in JIT (reflectDependencies → ReflectionCapabilities.parameters → ctorParameters()).
ngtsc keeps these imports.
Repro
// tokens.ts
import {InjectionToken} from '@angular/core';
export const TOKEN = new InjectionToken<unknown>('TOKEN');
// test.ts
import {Component, Inject, Optional} from '@angular/core';
import {TOKEN} from './tokens';
@Component({selector: 'c', template: ''})
export class C {
constructor(@Optional() @Inject(TOKEN) x: unknown) {}
}
// spec (plain node, @angular/core 22.1.7)
TestBed.initTestEnvironment(BrowserTestingModule, platformBrowserTesting());
TestBed.configureTestingModule({imports: [C], providers: [{provide: TOKEN, useValue: 1}, C]});
TestBed.overrideComponent(C, {set: {template: 'overridden'}});
TestBed.inject(C);
OXC (#504 tip and main, same output)
import { Component } from "@angular/core"; // Inject, Optional: gone
import * as i0 from '@angular/core';
import * as i1 from './tokens'; // `import {TOKEN}`: gone
export class C {
static ɵfac = function C_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || C)(i0.ɵɵdirectiveInject(i1.TOKEN,8));
};
...
}
(() =>{
(((typeof ngDevMode === "undefined") || ngDevMode) && i0.ɵsetClassMetadata(C,[{type:Component,
args:[{selector:"c",template:""}]}],() =>[{type:undefined,decorators:[{type:Optional},
{type:Inject,args:[TOKEN]}]}],null));
})();
Spec result: ReferenceError: Optional is not defined (without the overrideComponent line: ok).
ngtsc 22.1.7
import { Component, Inject, Optional } from '@angular/core';
import { TOKEN } from './tokens';
import * as i0 from "@angular/core";
...
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(C, [{
type: Component,
args: [{ selector: 'c', template: '' }]
}], () => [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [TOKEN]
}] }], null); })();
Spec result: ok.
The same happens in an @NgModule / @Directive / @Pipe / @Injectable constructor, and with a token declared in the same file (then only Inject / Optional dangle).
When it runs
emitClassMetadatadefaults totruein the Vite plugin (vite-plugin/index.ts~L124 / L255) and in the NAPI options (src/lib.rs~L262).- The call is behind
(typeof ngDevMode === "undefined" || ngDevMode). The Vite plugin setsngDevMode: 'false'only for production builds (angular-build-optimizer-plugin.ts, which also stripsɵsetClassMetadata). So it runs in dev serve and in tests (vitest + TestBed).
Where
crates/oxc_angular_compiler/src/component/import_elision.rs: PARAM_DECORATORS (~L53) and collect_ctor_param_decorator_only_imports / collect_uses_from_constructor_params (tip ~L331 / ~L512, main ~L329 / ~L500) mark these imports for removal without checking whether class metadata will still reference them. The metadata is built in class_metadata/builders.rs (build_ctor_params_metadata, ~L323) with the original bare names.
On main?
Yes.
Direction
Keep these imports whenever class metadata is emitted (emit_class_metadata && !advanced_optimizations), like ngtsc. Only remove them when no setClassMetadata is emitted.
- Vorherrschende Sprache
- Rust
- Sterne
- 232
- Forks
- 21
- Ø Merge
- 2 T. 14 Std.
- Gemergte PRs (30 T.)
- 30
Entwicklungsumgebung
Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus voidzero-dev/oxc-angular-compiler
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
voidzero-dev/oxc-angular-compiler#511 ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 78/100
voidzero-dev/oxc-angular-compiler#522 ·
Maintainer antworten meist innerhalb von 1 Tag
-
question
Schwierigkeit 5/5 Über eine Woche Anfängerfreundlichkeit 35/100
voidzero-dev/oxc-angular-compiler#521 ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 76/100
voidzero-dev/oxc-angular-compiler#519 ·
Maintainer antworten meist innerhalb von 1 Tag
-
enhancement
Schwierigkeit 5/5 Über eine Woche Anfängerfreundlichkeit 35/100
voidzero-dev/oxc-angular-compiler#518 ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in voidzero-dev/oxc-angular-compiler
Ähnliche Issues
-
area/cli parity
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 74/100
Maintainer antworten meist innerhalb von 1 Tag
-
A-Picking A-UI C-Bug D-Trivial S-Ready-For-Implementation
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
bevyengine/bevy#26029 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
-
ai_p3 comp-protocols
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 74/100
ClickHouse/ClickHouse#123884 ·
Maintainer antworten meist innerhalb von 1 Tag
-
state:needs triage
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 64/100
zed-industries/zed#65146 ·
Maintainer antworten meist innerhalb von 1 Tag