refactor(compiler): add ts-ignore comment on factory functions

Adds a `ts-ignore` comment to thew instantiation expressions in factories, because in some compilation modes we can't guarantee that they'll compile.
This commit is contained in:
Kristiyan Kostadinov
2026-03-18 10:35:58 +01:00
committed by Matthew Beck (Berry)
parent a8bf957086
commit c457b9b5b4
20 changed files with 111 additions and 141 deletions
@@ -1,5 +1,8 @@
export class MyOtherPipe {
…
static ɵfac = function MyOtherPipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MyOtherPipe)($i0$.ɵɵdirectiveInject($i0$.ChangeDetectorRef, 24)); };
static ɵfac = function MyOtherPipe_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || MyOtherPipe)($i0$.ɵɵdirectiveInject($i0$.ChangeDetectorRef, 24));
};
…
}
@@ -1,5 +1,8 @@
export class MyPipe {
…
static ɵfac = function MyPipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MyPipe)($i0$.ɵɵdirectiveInject($i0$.ChangeDetectorRef, 16)); };
static ɵfac = function MyPipe_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || MyPipe)($i0$.ɵɵdirectiveInject($i0$.ChangeDetectorRef, 16));
};
…
}
@@ -1,6 +1,7 @@
export class ForOfDirective {
…
static ɵfac = function ForOfDirective_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || ForOfDirective)($r3$.ɵɵdirectiveInject($r3$.ViewContainerRef), $r3$.ɵɵdirectiveInject($r3$.TemplateRef));
};
…
@@ -1,5 +1,8 @@
export class IfDirective {
…
static ɵfac = function IfDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || IfDirective)($r3$.ɵɵdirectiveInject($i$.TemplateRef)); };
static ɵfac = function IfDirective_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || IfDirective)($r3$.ɵɵdirectiveInject($i$.TemplateRef));
};
…
}
@@ -1,9 +1,8 @@
export class MyComponent {
// ...
static ɵfac = function MyComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || MyComponent)(
$r3$.ɵɵdirectiveInject($i$.ElementRef), $r3$.ɵɵdirectiveInject($i$.ViewContainerRef),
$r3$.ɵɵdirectiveInject($i$.ChangeDetectorRef));
/* @ts-ignore */
return new (__ngFactoryType__ || MyComponent)($r3$.ɵɵdirectiveInject($i$.ElementRef), $r3$.ɵɵdirectiveInject($i$.ViewContainerRef), $r3$.ɵɵdirectiveInject($i$.ChangeDetectorRef));
};
// ...
}
@@ -3,87 +3,57 @@
"cases": [
{
"description": "should define a basic NgModule (linked)",
"inputFiles": [
"basic_linked.ts"
],
"inputFiles": ["basic_linked.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"basic_linked.js"
]
"files": ["basic_linked.js"]
}
],
"compilationModeFilter": [
"linked compile",
"declaration-only emit"
]
"compilationModeFilter": ["linked compile", "declaration-only emit"]
},
{
"description": "should define a basic NgModule (full/local)",
"inputFiles": [
"basic_full.ts"
],
"description": "should define a basic NgModule (full/local)",
"inputFiles": ["basic_full.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"basic_full.js"
]
"files": ["basic_full.js"]
}
],
"compilationModeFilter": [
"full compile",
"local compile",
"declaration-only emit"
]
"compilationModeFilter": ["full compile", "local compile", "declaration-only emit"]
},
{
"description": "should define an NgModule with declarations and bootstrap",
"inputFiles": [
"declarations.ts"
],
"inputFiles": ["declarations.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"declarations.js"
]
"files": ["declarations.js"]
}
]
},
{
"description": "should define an NgModule with declarations and bootstrap (jit mode)",
"inputFiles": [
"declarations_jit_mode.ts"
],
"inputFiles": ["declarations_jit_mode.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"declarations_jit_mode.js"
]
"files": ["declarations_jit_mode.js"]
}
],
"compilationModeFilter": [
"linked compile",
"declaration-only emit"
],
"compilationModeFilter": ["linked compile", "declaration-only emit"],
"angularCompilerOptions": {
"linkerJitMode": true
}
},
{
"description": "should define an NgModule and injector with providers",
"inputFiles": [
"providers.ts"
],
"inputFiles": ["providers.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"providers.js"
]
"files": ["providers.js"]
}
],
"compilationModeFilter": [
@@ -95,55 +65,36 @@
},
{
"description": "should define NgModules with imports and exports",
"inputFiles": [
"imports_exports.ts"
],
"inputFiles": ["imports_exports.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"imports_exports.js"
]
"files": ["imports_exports.js"]
}
],
"compilationModeFilter": [
"full compile",
"local compile",
"declaration-only emit"
]
"compilationModeFilter": ["full compile", "local compile", "declaration-only emit"]
},
{
"description": "should define NgModules with imports and exports (jit mode)",
"inputFiles": [
"imports_exports_jit_mode.ts"
],
"inputFiles": ["imports_exports_jit_mode.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"imports_exports_jit_mode.js"
]
"files": ["imports_exports_jit_mode.js"]
}
],
"compilationModeFilter": [
"linked compile",
"declaration-only emit"
],
"compilationModeFilter": ["linked compile", "declaration-only emit"],
"angularCompilerOptions": {
"linkerJitMode": true
}
},
{
"description": "should not process NgModules that are marked `jit`",
"inputFiles": [
"no_aot.ts"
],
"inputFiles": ["no_aot.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"no_aot.js"
]
"files": ["no_aot.js"]
}
],
"compilationModeFilter": [
@@ -155,15 +106,11 @@
},
{
"description": "should handle NgModules that extend other classes",
"inputFiles": [
"inheritance.ts"
],
"inputFiles": ["inheritance.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"inheritance.js"
]
"files": ["inheritance.js"]
}
],
"compilationModeFilter": [
@@ -175,36 +122,25 @@
},
{
"description": "should handle NgModules with forward refs",
"inputFiles": [
"forward_refs.ts"
],
"inputFiles": ["forward_refs.ts"],
"expectations": [
{
"failureMessage": "Invalid NgModule/Injector definition",
"files": [
"forward_refs.js"
]
"files": ["forward_refs.js"]
}
],
"compilationModeFilter": [
"linked compile",
"declaration-only emit"
],
"compilationModeFilter": ["linked compile", "declaration-only emit"],
"angularCompilerOptions": {
"linkerJitMode": true
}
},
{
"description": "should not pass along empty array fields to the declaration",
"inputFiles": [
"empty_fields.ts"
],
"inputFiles": ["empty_fields.ts"],
"expectations": [
{
"failureMessage": "Empty declaration exists",
"files": [
"empty_fields.js"
]
"files": ["empty_fields.js"]
}
],
"compilationModeFilter": [
@@ -216,15 +152,11 @@
},
{
"description": "should handle providers passed in as a variable",
"inputFiles": [
"variable_providers.ts"
],
"inputFiles": ["variable_providers.ts"],
"expectations": [
{
"failureMessage": "Invalid injector definition",
"files": [
"variable_providers.js"
]
"files": ["variable_providers.js"]
}
],
"compilationModeFilter": [
@@ -1,7 +1,10 @@
export class BaseModule {
// ...
constructor(service) { this.service = service; }
static ɵfac = function BaseModule_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || BaseModule)(i0.ɵɵinject(Service)); };
static ɵfac = function BaseModule_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || BaseModule)(i0.ɵɵinject(Service));
};
static ɵmod = /*@__PURE__*/ i0.ɵɵdefineNgModule({ type: BaseModule });
static ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ providers: [Service] });
}
@@ -1,7 +1,10 @@
export class BaseModule {
…
constructor(service) { this.service = service; }
static ɵfac = function BaseModule_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || BaseModule)(i0.ɵɵinject(Service)); };
static ɵfac = function BaseModule_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || BaseModule)(i0.ɵɵinject(Service));
};
static ɵmod = /*@__PURE__*/ i0.ɵɵdefineNgModule({ type: BaseModule });
static ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ providers: [Service] });
}
@@ -1,16 +1,8 @@
export class MyComponent {
// ...
static ɵfac = function MyComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || MyComponent)(
$r3$.ɵɵinjectAttribute('name'),
$r3$.ɵɵinjectAttribute(dynamicAttrName()),
$r3$.ɵɵdirectiveInject(MyService),
$r3$.ɵɵdirectiveInject(MyService, 1),
$r3$.ɵɵdirectiveInject(MyService, 2),
$r3$.ɵɵdirectiveInject(MyService, 4),
$r3$.ɵɵdirectiveInject(MyService, 8),
$r3$.ɵɵdirectiveInject(MyService, 10)
);
/* @ts-ignore */
return new (__ngFactoryType__ || MyComponent)($r3$.ɵɵinjectAttribute('name'), $r3$.ɵɵinjectAttribute(dynamicAttrName()), $r3$.ɵɵdirectiveInject(MyService), $r3$.ɵɵdirectiveInject(MyService, 1), $r3$.ɵɵdirectiveInject(MyService, 2), $r3$.ɵɵdirectiveInject(MyService, 4), $r3$.ɵɵdirectiveInject(MyService, 8), $r3$.ɵɵdirectiveInject(MyService, 10));
}
// ...
}
@@ -1,6 +1,7 @@
export class MyService {
// ...
static ɵfac = function MyService_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || MyService)($r3$.ɵɵinject(MyDependency), $r3$.ɵɵinject(MyOptionalDependency, 8));
}
// ...
@@ -1,6 +1,7 @@
export class MyService {
// ...
static ɵfac = function MyService_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || MyService)($r3$.ɵɵinject(MyDependency));
}
// ...
@@ -1,7 +1,10 @@
// NOTE The prov definition must be last so MyOtherPipe.fac is defined
export class MyOtherPipe {
// ...
static ɵfac = function MyOtherPipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MyOtherPipe)(i0.ɵɵdirectiveInject(Service, 16)); };
static ɵfac = function MyOtherPipe_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || MyOtherPipe)(i0.ɵɵdirectiveInject(Service, 16));
};
static ɵpipe = /*@__PURE__*/ i0.ɵɵdefinePipe({ name: "myOtherPipe", type: MyOtherPipe, pure: true, standalone: false });
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MyOtherPipe, factory: MyOtherPipe.ɵfac });
}
@@ -1,7 +1,10 @@
// NOTE The prov definition must be last so MyPipe.fac is defined
export class MyPipe {
// ...
static ɵfac = function MyPipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MyPipe)(i0.ɵɵdirectiveInject(Service, 16)); };
static ɵfac = function MyPipe_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || MyPipe)(i0.ɵɵdirectiveInject(Service, 16));
};
static ɵpipe = /*@__PURE__*/ i0.ɵɵdefinePipe({ name: "myPipe", type: MyPipe, pure: true, standalone: false });
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MyPipe, factory: MyPipe.ɵfac });
}
@@ -1,6 +1,9 @@
export class Service {
…
static ɵfac = function Service_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || Service)($i0$.ɵɵinject(Dep)); };
static ɵfac = function Service_Factory(__ngFactoryType__) {
/* @ts-ignore */
return new (__ngFactoryType__ || Service)($i0$.ɵɵinject(Dep));
};
static ɵprov = /*@__PURE__*/ $i0$.ɵɵdefineInjectable({ token: Service, factory: Service.ɵfac, providedIn: $i0$.forwardRef(() => Mod) });
}
@@ -7,6 +7,7 @@ export class MyService {
if (__ngFactoryType__) {
__ngConditionalFactory__ = new __ngFactoryType__();
} else {
/* @ts-ignore */
__ngConditionalFactory__ = new MyAlternateService($r3$.ɵɵinject(SomeDep));
}
return __ngConditionalFactory__;
@@ -7,6 +7,7 @@ export class MyService {
if (__ngFactoryType__) {
__ngConditionalFactory__ = new __ngFactoryType__();
} else {
/* @ts-ignore */
__ngConditionalFactory__ = ((dep, optional) => new MyAlternateService(dep, optional))($r3$.ɵɵinject(SomeDep), $r3$.ɵɵinject(SomeDep, 8));
}
return __ngConditionalFactory__;
@@ -1048,7 +1048,7 @@ runInEachFileSystem(() => {
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
`MainComponent.ɵfac = function MainComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MainComponent)(i0.ɵɵdirectiveInject(i1.SomeService1), i0.ɵɵdirectiveInject(SomeService2), i0.ɵɵdirectiveInject(i2.SomeService3), i0.ɵɵdirectiveInject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN)); };`,
`MainComponent.ɵfac = function MainComponent_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || MainComponent)(i0.ɵɵdirectiveInject(i1.SomeService1), i0.ɵɵdirectiveInject(SomeService2), i0.ɵɵdirectiveInject(i2.SomeService3), i0.ɵɵdirectiveInject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN)); };`,
);
});
@@ -1084,7 +1084,7 @@ runInEachFileSystem(() => {
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
`MainComponent.ɵfac = function MainComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MainComponent)(i0.ɵɵdirectiveInject(i1.SomeService1), i0.ɵɵdirectiveInject(SomeService2), i0.ɵɵdirectiveInject(i2.SomeService3), i0.ɵɵdirectiveInject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN)); };`,
`MainComponent.ɵfac = function MainComponent_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || MainComponent)(i0.ɵɵdirectiveInject(i1.SomeService1), i0.ɵɵdirectiveInject(SomeService2), i0.ɵɵdirectiveInject(i2.SomeService3), i0.ɵɵdirectiveInject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN)); };`,
);
});
@@ -1124,7 +1124,7 @@ runInEachFileSystem(() => {
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
`MainDirective.ɵfac = function MainDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MainDirective)(i0.ɵɵdirectiveInject(i1.SomeService1), i0.ɵɵdirectiveInject(SomeService2), i0.ɵɵdirectiveInject(i2.SomeService3), i0.ɵɵdirectiveInject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN)); };`,
`MainDirective.ɵfac = function MainDirective_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || MainDirective)(i0.ɵɵdirectiveInject(i1.SomeService1), i0.ɵɵdirectiveInject(SomeService2), i0.ɵɵdirectiveInject(i2.SomeService3), i0.ɵɵdirectiveInject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN)); };`,
);
});
@@ -1157,7 +1157,7 @@ runInEachFileSystem(() => {
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
`MainDirective.ɵfac = function MainDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MainDirective)(i0.ɵɵdirectiveInject(i1.SomeService1), i0.ɵɵdirectiveInject(SomeService2), i0.ɵɵdirectiveInject(i2.SomeService3), i0.ɵɵdirectiveInject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN)); };`,
`MainDirective.ɵfac = function MainDirective_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || MainDirective)(i0.ɵɵdirectiveInject(i1.SomeService1), i0.ɵɵdirectiveInject(SomeService2), i0.ɵɵdirectiveInject(i2.SomeService3), i0.ɵɵdirectiveInject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN)); };`,
);
});
@@ -1196,7 +1196,7 @@ runInEachFileSystem(() => {
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
`MainPipe.ɵfac = function MainPipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MainPipe)(i0.ɵɵdirectiveInject(i1.SomeService1, 16), i0.ɵɵdirectiveInject(SomeService2, 16), i0.ɵɵdirectiveInject(i2.SomeService3, 16), i0.ɵɵdirectiveInject(i3.nested.SomeService4, 16), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN, 16)); };`,
`MainPipe.ɵfac = function MainPipe_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || MainPipe)(i0.ɵɵdirectiveInject(i1.SomeService1, 16), i0.ɵɵdirectiveInject(SomeService2, 16), i0.ɵɵdirectiveInject(i2.SomeService3, 16), i0.ɵɵdirectiveInject(i3.nested.SomeService4, 16), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN, 16)); };`,
);
});
@@ -1229,7 +1229,7 @@ runInEachFileSystem(() => {
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
`MainPipe.ɵfac = function MainPipe_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MainPipe)(i0.ɵɵdirectiveInject(i1.SomeService1, 16), i0.ɵɵdirectiveInject(SomeService2, 16), i0.ɵɵdirectiveInject(i2.SomeService3, 16), i0.ɵɵdirectiveInject(i3.nested.SomeService4, 16), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN, 16)); };`,
`MainPipe.ɵfac = function MainPipe_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || MainPipe)(i0.ɵɵdirectiveInject(i1.SomeService1, 16), i0.ɵɵdirectiveInject(SomeService2, 16), i0.ɵɵdirectiveInject(i2.SomeService3, 16), i0.ɵɵdirectiveInject(i3.nested.SomeService4, 16), i0.ɵɵinjectAttribute('title'), i0.ɵɵdirectiveInject(MESSAGE_TOKEN, 16)); };`,
);
});
@@ -1264,7 +1264,7 @@ runInEachFileSystem(() => {
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
`MainService.ɵfac = function MainService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MainService)(i0.ɵɵinject(i1.SomeService1), i0.ɵɵinject(SomeService2), i0.ɵɵinject(i2.SomeService3), i0.ɵɵinject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵinject(MESSAGE_TOKEN)); };`,
`MainService.ɵfac = function MainService_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || MainService)(i0.ɵɵinject(i1.SomeService1), i0.ɵɵinject(SomeService2), i0.ɵɵinject(i2.SomeService3), i0.ɵɵinject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵinject(MESSAGE_TOKEN)); };`,
);
});
@@ -1298,7 +1298,7 @@ runInEachFileSystem(() => {
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
`MainModule.ɵfac = function MainModule_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MainModule)(i0.ɵɵinject(i1.SomeService1), i0.ɵɵinject(SomeService2), i0.ɵɵinject(i2.SomeService3), i0.ɵɵinject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵinject(MESSAGE_TOKEN)); };`,
`MainModule.ɵfac = function MainModule_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || MainModule)(i0.ɵɵinject(i1.SomeService1), i0.ɵɵinject(SomeService2), i0.ɵɵinject(i2.SomeService3), i0.ɵɵinject(i3.nested.SomeService4), i0.ɵɵinjectAttribute('title'), i0.ɵɵinject(MESSAGE_TOKEN)); };`,
);
});
+11 -7
View File
@@ -162,7 +162,7 @@ runInEachFileSystem((os: string) => {
expect(jsContents).toContain('Dep.ɵprov =');
expect(jsContents).toContain('Service.ɵprov =');
expect(jsContents).toContain(
'Service.ɵfac = function Service_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep)); };',
'Service.ɵfac = function Service_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep)); };',
);
expect(jsContents).toContain("providedIn: 'root' })");
expect(jsContents).not.toContain('__decorate');
@@ -494,7 +494,9 @@ runInEachFileSystem((os: string) => {
expect(jsContents).toContain(
'factory: function Service_Factory(__ngFactoryType__) { let __ngConditionalFactory__ = null; if (__ngFactoryType__) {',
);
expect(jsContents).toContain('return new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep));');
expect(jsContents).toContain(
'/* @ts-ignore */\nreturn new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep));',
);
expect(jsContents).toContain(
'__ngConditionalFactory__ = ((dep) => new Service(dep))(i0.ɵɵinject(Dep));',
);
@@ -532,7 +534,9 @@ runInEachFileSystem((os: string) => {
expect(jsContents).toContain(
'factory: function Service_Factory(__ngFactoryType__) { let __ngConditionalFactory__ = null; if (__ngFactoryType__) {',
);
expect(jsContents).toContain('return new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep));');
expect(jsContents).toContain(
'/* @ts-ignore */\nreturn new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep));',
);
expect(jsContents).toContain(
'__ngConditionalFactory__ = ((dep) => new Service(dep))(i0.ɵɵinject(Dep, 10));',
);
@@ -569,7 +573,7 @@ runInEachFileSystem((os: string) => {
expect(jsContents).toContain('Service.ɵprov =');
expect(jsContents).toContain('Mod.ɵmod =');
expect(jsContents).toContain(
'Service.ɵfac = function Service_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep)); };',
'Service.ɵfac = function Service_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep)); };',
);
expect(jsContents).toContain('providedIn: i0.forwardRef(() => Mod) })');
expect(jsContents).not.toContain('__decorate');
@@ -626,7 +630,7 @@ runInEachFileSystem((os: string) => {
expect(jsContents).toContain(
`Service.ɵfac = function Service_Factory(__ngFactoryType__) { ` +
`return new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep), i0.ɵɵinject(OptionalDep, 8)); };`,
`/* @ts-ignore */\nreturn new (__ngFactoryType__ || Service)(i0.ɵɵinject(Dep), i0.ɵɵinject(OptionalDep, 8)); };`,
);
});
@@ -5123,7 +5127,7 @@ runInEachFileSystem((os: string) => {
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
`FooCmp.ɵfac = function FooCmp_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FooCmp)(i0.ɵɵinjectAttribute("test"), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i0.TemplateRef), i0.ɵɵdirectiveInject(i0.ViewContainerRef)); }`,
`FooCmp.ɵfac = function FooCmp_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || FooCmp)(i0.ɵɵinjectAttribute("test"), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i0.TemplateRef), i0.ɵɵdirectiveInject(i0.ViewContainerRef)); }`,
);
});
@@ -6168,7 +6172,7 @@ runInEachFileSystem((os: string) => {
const jsContents = env.getContents('test.js');
expect(jsContents).toContain(
'function Base_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || Base)(i0.ɵɵinject(Dep)); }',
'function Base_Factory(__ngFactoryType__) { /* @ts-ignore */\nreturn new (__ngFactoryType__ || Base)(i0.ɵɵinject(Dep)); }',
);
expect(jsContents).toContain(
'(() => { let ɵChild_BaseFactory; return function Child_Factory(__ngFactoryType__) { return (ɵChild_BaseFactory || (ɵChild_BaseFactory = i0.ɵɵgetInheritedFactory(Child)))(__ngFactoryType__ || Child); }; })();',
+2 -2
View File
@@ -317,8 +317,8 @@ export abstract class Expression {
return new BinaryOperatorExpr(BinaryOperator.NullishCoalesce, this, rhs, null, sourceSpan);
}
toStmt(): Statement {
return new ExpressionStatement(this, null);
toStmt(leadingComments?: LeadingComment[]): Statement {
return new ExpressionStatement(this, null, leadingComments);
}
}
+18 -4
View File
@@ -10,7 +10,7 @@ import {InjectFlags} from '../core';
import * as o from '../output/output_ast';
import {Identifiers as R3} from '../render3/r3_identifiers';
import {R3CompiledExpression, R3Reference, typeWithParameters} from './util';
import {R3CompiledExpression, R3Reference, tsIgnoreComment, typeWithParameters} from './util';
/**
* Metadata required by the factory generator to generate a `factory` function for a type.
@@ -117,6 +117,19 @@ export function compileFactoryFunction(meta: R3FactoryMetadata): R3CompiledExpre
: t;
let ctorExpr: o.Expression | null = null;
// If the factory has invalid dependencies (e.g. trying to inject an interface), we normally mark
// the `deps` as invalid so we can emit an invalid factory. In some environments we may not
// be able to determine if the dependency is invalid, because that depends on information in
// other files. To ensure that cases like that still compile, we need to add a `@ts-ignore`
// comment which allows the code to compile and then error at runtime. Note that it's important
// to put the comment on a statement, because it includes a new line which may break `return`
// statements if the comment is set on the expression.
const factoryComments =
meta.deps !== null && meta.deps !== 'invalid' && meta.deps.length > 0
? [tsIgnoreComment()]
: undefined;
if (meta.deps !== null) {
// There is a constructor (either explicitly or implicitly defined).
if (meta.deps !== 'invalid') {
@@ -136,9 +149,10 @@ export function compileFactoryFunction(meta: R3FactoryMetadata): R3CompiledExpre
body.push(new o.DeclareVarStmt(r.name, o.NULL_EXPR, o.DYNAMIC_TYPE));
const ctorStmt =
ctorExpr !== null
? r.set(ctorExpr).toStmt()
? r.set(ctorExpr).toStmt(factoryComments)
: o.importExpr(R3.invalidFactory).callFn([]).toStmt();
body.push(o.ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt()]));
// Always add a `ts-ignore` on the alternate factory.
body.push(o.ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt([tsIgnoreComment()])]));
return r;
}
@@ -173,7 +187,7 @@ export function compileFactoryFunction(meta: R3FactoryMetadata): R3CompiledExpre
body.push(new o.ReturnStatement(baseFactory.callFn([typeForCtor])));
} else {
// This is straightforward factory, just return it.
body.push(new o.ReturnStatement(retExpr));
body.push(new o.ReturnStatement(retExpr, null, factoryComments));
}
let factoryFn: o.Expression = o.fn(