Skip to content

Commit

Permalink
refactor(compiler): move factory out of injector definition (#41022) (#…
Browse files Browse the repository at this point in the history
…41133)

Previously, injector definitions contained a `factory` property that
was used to create a new instance of the associated NgModule class.

Now this factory has been moved to its own `ɵfac` static property on the
NgModule class itself. This is inline with how directives, components and
pipes are created.

There is a small size increase to bundle sizes for each NgModule class,
because the `ɵfac` takes up a bit more space:

Before:

```js
let a = (() => {
  class n {}
  return n.\u0275mod = c.Cb({type: n}),
  n.\u0275inj = c.Bb({factory: function(t) { return new (t || n) }, imports: [[e.a.forChild(s)], e.a]}),
  n
})(),
```

After:

```js
let a = (() => {
  class n {}
  return n.\u0275fac = function(t) { return new (t || n) },
  n.\u0275mod = c.Cb({type: n}),
  n.\u0275inj = c.Bb({imports: [[r.a.forChild(s)], r.a]}),
  n
})(),
```

In other words `n.\u0275fac = ` is longer than `factory: ` (by 5 characters)
and only because the tooling insists on encoding `ɵ` as `\u0275`.

This can be mitigated in a future PR by only generating the `ɵfac` property
if it is actually needed.

PR Close #41022

PR Close #41133
  • Loading branch information
petebacondarwin authored and AndrewKushnir committed Mar 9, 2021
1 parent b770e69 commit 1bebd66
Show file tree
Hide file tree
Showing 64 changed files with 840 additions and 445 deletions.
1 change: 1 addition & 0 deletions goldens/public-api/core/core.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ export declare abstract class Injector {
export declare const INJECTOR: InjectionToken<Injector>;

export declare interface InjectorType<T> extends Type<T> {
ɵfac?: unknown;
ɵinj: unknown;
}

Expand Down
8 changes: 4 additions & 4 deletions goldens/size-tracking/integration-payloads.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
"master": {
"uncompressed": {
"runtime-es2015": 2285,
"main-es2015": 239910,
"polyfills-es2015": 36709,
"5-es2015": 745
"main-es2015": 239929,
"polyfills-es2015": 36973,
"5-es2015": 753
}
}
},
Expand Down Expand Up @@ -75,4 +75,4 @@
}
}
}
}
}
44 changes: 20 additions & 24 deletions packages/compiler-cli/src/ngtsc/annotations/src/ng_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {compileFactoryFunction, compileInjector, compileNgModule, CUSTOM_ELEMENTS_SCHEMA, Expression, ExternalExpr, Identifiers as R3, InvokeFunctionExpr, LiteralArrayExpr, LiteralExpr, NO_ERRORS_SCHEMA, R3FactoryTarget, R3Identifiers, R3InjectorMetadata, R3NgModuleMetadata, R3Reference, SchemaMetadata, Statement, STRING_TYPE, WrappedNodeExpr} from '@angular/compiler';
import {compileInjector, compileNgModule, CUSTOM_ELEMENTS_SCHEMA, Expression, ExternalExpr, Identifiers as R3, InvokeFunctionExpr, LiteralArrayExpr, LiteralExpr, NO_ERRORS_SCHEMA, R3DependencyMetadata, R3FactoryTarget, R3Identifiers, R3InjectorMetadata, R3NgModuleMetadata, R3Reference, SchemaMetadata, Statement, STRING_TYPE, WrappedNodeExpr} from '@angular/compiler';
import * as ts from 'typescript';

import {ErrorCode, FatalDiagnosticError, makeDiagnostic, makeRelatedInformation} from '../../diagnostics';
Expand All @@ -22,13 +22,15 @@ import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPr
import {getSourceFile} from '../../util/src/typescript';

import {createValueHasWrongTypeError, getProviderDiagnostics} from './diagnostics';
import {compileNgFactoryDefField} from './factory';
import {generateSetClassMetadataCall} from './metadata';
import {ReferencesRegistry} from './references_registry';
import {combineResolvers, findAngularDecorator, forwardRefResolver, getValidConstructorDependencies, isExpressionForwardReference, resolveProvidersRequiringFactory, toR3Reference, unwrapExpression, wrapFunctionExpressionsInParens, wrapTypeReference} from './util';

export interface NgModuleAnalysis {
mod: R3NgModuleMetadata;
inj: R3InjectorMetadata;
deps: R3DependencyMetadata[]|null;
metadataStmt: Statement|null;
declarations: Reference<ClassDeclaration>[];
rawDeclarations: ts.Expression|null;
Expand Down Expand Up @@ -118,8 +120,6 @@ export class NgModuleSymbol extends SemanticSymbol {

/**
* Compiles @NgModule annotations to ngModuleDef fields.
*
* TODO(alxhub): handle injector side of things as well.
*/
export class NgModuleDecoratorHandler implements
DecoratorHandler<Decorator, NgModuleAnalysis, NgModuleSymbol, NgModuleResolution> {
Expand Down Expand Up @@ -337,8 +337,6 @@ export class NgModuleDecoratorHandler implements
name,
type,
internalType,
deps: getValidConstructorDependencies(
node, this.reflector, this.defaultImportRecorder, this.isCore),
providers: wrapperProviders,
imports: injectorImports,
};
Expand All @@ -349,6 +347,8 @@ export class NgModuleDecoratorHandler implements
schemas: schemas,
mod: ngModuleDef,
inj: ngInjectorDef,
deps: getValidConstructorDependencies(
node, this.reflector, this.defaultImportRecorder, this.isCore),
declarations: declarationRefs,
rawDeclarations,
imports: importRefs,
Expand Down Expand Up @@ -449,26 +449,13 @@ export class NgModuleDecoratorHandler implements
}

compileFull(
node: ClassDeclaration, {inj, mod, metadataStmt, declarations}: Readonly<NgModuleAnalysis>,
node: ClassDeclaration,
{inj, mod, deps, metadataStmt, declarations}: Readonly<NgModuleAnalysis>,
resolution: Readonly<NgModuleResolution>): CompileResult[] {
const factoryFn = compileFactoryFunction({
name: inj.name,
type: inj.type,
internalType: inj.internalType,
typeArgumentCount: 0,
deps: inj.deps,
injectFn: R3.inject,
target: R3FactoryTarget.NgModule,
});

// Merge the injector imports (which are 'exports' that were later found to be NgModules)
// computed during resolution with the ones from analysis.
const ngInjectorDef = compileInjector(
{
...inj,
imports: [...inj.imports, ...resolution.injectorImports],
},
factoryFn);
const ngInjectorDef =
compileInjector({...inj, imports: [...inj.imports, ...resolution.injectorImports]});
const ngModuleDef = compileNgModule(mod);
const ngModuleStatements = ngModuleDef.additionalStatements;
if (metadataStmt !== null) {
Expand All @@ -492,6 +479,15 @@ export class NgModuleDecoratorHandler implements
}
}
const res: CompileResult[] = [
compileNgFactoryDefField({
name: inj.name,
type: inj.type,
internalType: inj.internalType,
typeArgumentCount: 0,
deps,
injectFn: R3.inject,
target: R3FactoryTarget.NgModule,
}),
{
name: 'ɵmod',
initializer: ngModuleDef.expression,
Expand All @@ -501,9 +497,9 @@ export class NgModuleDecoratorHandler implements
{
name: 'ɵinj',
initializer: ngInjectorDef.expression,
statements: ngInjectorDef.statements,
statements: [],
type: ngInjectorDef.type,
}
},
];

if (this.localeId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ MyForwardDirective.ɵdir = i0.ɵɵngDeclareDirective({ version: "0.0.0-PLACEHOLD
}], null, null); })();
export class MyModule {
}
MyModule.ɵfac = function MyModule_Factory(t) { return new (t || MyModule)(); };
MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
MyModule.ɵinj = i0.ɵɵdefineInjector({});
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [HostBindingComp, MyForwardDirective] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyModule, [{
type: NgModule,
Expand All @@ -45,6 +46,7 @@ export declare class HostBindingComp {
static ɵcmp: i0.ɵɵComponentDefWithMeta<HostBindingComp, "host-binding-comp", never, {}, {}, never, never>;
}
export declare class MyModule {
static ɵfac: i0.ɵɵFactoryDef<MyModule, never>;
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MyModule, [typeof HostBindingComp, typeof MyForwardDirective], never, never>;
static ɵinj: i0.ɵɵInjectorDef<MyModule>;
}
Expand Down Expand Up @@ -79,8 +81,9 @@ MyForwardPipe.ɵpipe = i0.ɵɵngDeclarePipe({ version: "0.0.0-PLACEHOLDER", ngIm
}], null, null); })();
export class MyModule {
}
MyModule.ɵfac = function MyModule_Factory(t) { return new (t || MyModule)(); };
MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
MyModule.ɵinj = i0.ɵɵdefineInjector({});
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [HostBindingComp, MyForwardPipe] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyModule, [{
type: NgModule,
Expand All @@ -96,6 +99,7 @@ export declare class HostBindingComp {
static ɵcmp: i0.ɵɵComponentDefWithMeta<HostBindingComp, "host-binding-comp", never, {}, {}, never, never>;
}
export declare class MyModule {
static ɵfac: i0.ɵɵFactoryDef<MyModule, never>;
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MyModule, [typeof HostBindingComp, typeof MyForwardPipe], never, never>;
static ɵinj: i0.ɵɵInjectorDef<MyModule>;
}
Expand All @@ -115,8 +119,9 @@ SomeDirective.ɵdir = i0.ɵɵngDeclareDirective({ version: "0.0.0-PLACEHOLDER",
}], null, null); })();
export class MyModule {
}
MyModule.ɵfac = function MyModule_Factory(t) { return new (t || MyModule)(); };
MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
MyModule.ɵinj = i0.ɵɵdefineInjector({});
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [SomeDirective] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyModule, [{
type: NgModule,
Expand All @@ -132,6 +137,7 @@ export declare class SomeDirective {
static ɵdir: i0.ɵɵDirectiveDefWithMeta<SomeDirective, "[some-directive]", ["someDir", "otherDir"], {}, {}, never>;
}
export declare class MyModule {
static ɵfac: i0.ɵɵFactoryDef<MyModule, never>;
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MyModule, [typeof SomeDirective], never, never>;
static ɵinj: i0.ɵɵInjectorDef<MyModule>;
}
Expand Down Expand Up @@ -185,8 +191,9 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: My
}], null, null); })();
export class MyMod {
}
MyMod.ɵfac = function MyMod_Factory(t) { return new (t || MyMod)(); };
MyMod.ɵmod = i0.ɵɵdefineNgModule({ type: MyMod });
MyMod.ɵinj = i0.ɵɵdefineInjector({ factory: function MyMod_Factory(t) { return new (t || MyMod)(); } });
MyMod.ɵinj = i0.ɵɵdefineInjector({});
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyMod, { declarations: [SomeComp, MyApp] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyMod, [{
type: NgModule,
Expand All @@ -208,6 +215,7 @@ export declare class MyApp {
static ɵcmp: i0.ɵɵComponentDefWithMeta<MyApp, "ng-component", never, {}, {}, never, never>;
}
export declare class MyMod {
static ɵfac: i0.ɵɵFactoryDef<MyMod, never>;
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MyMod, [typeof SomeComp, typeof MyApp], never, never>;
static ɵinj: i0.ɵɵInjectorDef<MyMod>;
}
Expand Down Expand Up @@ -239,8 +247,9 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: My
}], null, null); })();
export class MyMod {
}
MyMod.ɵfac = function MyMod_Factory(t) { return new (t || MyMod)(); };
MyMod.ɵmod = i0.ɵɵdefineNgModule({ type: MyMod });
MyMod.ɵinj = i0.ɵɵdefineInjector({ factory: function MyMod_Factory(t) { return new (t || MyMod)(); } });
MyMod.ɵinj = i0.ɵɵdefineInjector({});
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyMod, { declarations: [MyApp, SomeComp] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyMod, [{
type: NgModule,
Expand All @@ -262,6 +271,7 @@ export declare class MyApp {
static ɵcmp: i0.ɵɵComponentDefWithMeta<MyApp, "ng-component", never, {}, {}, never, never>;
}
export declare class MyMod {
static ɵfac: i0.ɵɵFactoryDef<MyMod, never>;
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MyMod, [typeof MyApp, typeof SomeComp], never, never>;
static ɵinj: i0.ɵɵInjectorDef<MyMod>;
}
Expand Down Expand Up @@ -289,8 +299,9 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: My
}], null, null); })();
export class MyModule {
}
MyModule.ɵfac = function MyModule_Factory(t) { return new (t || MyModule)(); };
MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
MyModule.ɵinj = i0.ɵɵdefineInjector({});
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyApp] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyModule, [{
type: NgModule,
Expand All @@ -306,6 +317,7 @@ export declare class MyApp {
static ɵcmp: i0.ɵɵComponentDefWithMeta<MyApp, "ng-component", never, {}, {}, never, never>;
}
export declare class MyModule {
static ɵfac: i0.ɵɵFactoryDef<MyModule, never>;
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MyModule, [typeof MyApp], never, never>;
static ɵinj: i0.ɵɵInjectorDef<MyModule>;
}
Expand Down Expand Up @@ -333,8 +345,9 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: My
}], null, null); })();
export class MyModule {
}
MyModule.ɵfac = function MyModule_Factory(t) { return new (t || MyModule)(); };
MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
MyModule.ɵinj = i0.ɵɵdefineInjector({});
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyApp] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyModule, [{
type: NgModule,
Expand All @@ -350,6 +363,7 @@ export declare class MyApp {
static ɵcmp: i0.ɵɵComponentDefWithMeta<MyApp, "ng-component", never, {}, {}, never, never>;
}
export declare class MyModule {
static ɵfac: i0.ɵɵFactoryDef<MyModule, never>;
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MyModule, [typeof MyApp], never, never>;
static ɵinj: i0.ɵɵInjectorDef<MyModule>;
}
Expand Down Expand Up @@ -380,8 +394,9 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: My
}], null, null); })();
export class MyModule {
}
MyModule.ɵfac = function MyModule_Factory(t) { return new (t || MyModule)(); };
MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
MyModule.ɵinj = i0.ɵɵdefineInjector({});
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyApp] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyModule, [{
type: NgModule,
Expand All @@ -398,6 +413,7 @@ export declare class MyApp {
static ɵcmp: i0.ɵɵComponentDefWithMeta<MyApp, "ng-component", never, {}, {}, never, never>;
}
export declare class MyModule {
static ɵfac: i0.ɵɵFactoryDef<MyModule, never>;
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MyModule, [typeof MyApp], never, never>;
static ɵinj: i0.ɵɵInjectorDef<MyModule>;
}
Expand Down Expand Up @@ -463,8 +479,9 @@ MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", ty
}], null, null); })();
export class MyModule {
}
MyModule.ɵfac = function MyModule_Factory(t) { return new (t || MyModule)(); };
MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
MyModule.ɵinj = i0.ɵɵdefineInjector({});
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyModule, [{
type: NgModule,
Expand All @@ -480,6 +497,7 @@ export declare class MyComponent {
static ɵcmp: i0.ɵɵComponentDefWithMeta<MyComponent, "my-app", never, {}, {}, never, never>;
}
export declare class MyModule {
static ɵfac: i0.ɵɵFactoryDef<MyModule, never>;
static ɵmod: i0.ɵɵNgModuleDefWithMeta<MyModule, [typeof MyComponent], never, never>;
static ɵinj: i0.ɵɵInjectorDef<MyModule>;
}
Expand Down

0 comments on commit 1bebd66

Please sign in to comment.