refactor(ivy): generate ngFactoryDef for injectables (#32433)

With #31953 we moved the factories for components, directives and pipes into a new field called `ngFactoryDef`, however I decided not to do it for injectables, because they needed some extra logic. These changes set up the `ngFactoryDef` for injectables as well.

For reference, the extra logic mentioned above is that for injectables we have two code paths:

1. For injectables that don't configure how they should be instantiated, we create a `factory` that proxies to `ngFactoryDef`:

```
// Source
@Injectable()
class Service {}

// Output
class Service {
  static ngInjectableDef = defineInjectable({
    factory: () => Service.ngFactoryFn(),
  });

  static ngFactoryFn: (t) => new (t || Service)();
}
```

2. For injectables that do configure how they're created, we keep the `ngFactoryDef` and generate the factory based on the metadata:

```
// Source
@Injectable({
  useValue: DEFAULT_IMPL,
})
class Service {}

// Output
export class Service {
  static ngInjectableDef = defineInjectable({
    factory: () => DEFAULT_IMPL,
  });

  static ngFactoryFn: (t) => new (t || Service)();
}
```

PR Close #32433
This commit is contained in:
crisbeto
2019-09-01 12:26:04 +02:00
committed by atscott
parent 2729747225
commit 4e35e348af
33 changed files with 695 additions and 295 deletions

View File

@ -86,7 +86,8 @@ export interface R3FactoryDefMetadata {
name: string;
type: o.Expression;
typeArgumentCount: number;
deps: R3DependencyMetadata[]|null;
deps: R3DependencyMetadata[]|'invalid'|null;
injectFn: o.ExternalReference;
isPipe?: boolean;
}
@ -267,8 +268,7 @@ export function compileFactoryFromMetadata(meta: R3FactoryDefMetadata): R3Factor
type: meta.type,
deps: meta.deps,
typeArgumentCount: meta.typeArgumentCount,
// TODO(crisbeto): this should be refactored once we start using it for injectables.
injectFn: R3.directiveInject,
injectFn: meta.injectFn,
},
meta.isPipe);
}

View File

@ -89,7 +89,8 @@ export function compilePipeFromRender2(
pure: pipe.pure,
};
const res = compilePipeFromMetadata(metadata);
const factoryRes = compileFactoryFromMetadata({...metadata, isPipe: true});
const factoryRes =
compileFactoryFromMetadata({...metadata, injectFn: R3.directiveInject, isPipe: true});
const definitionField = outputCtx.constantPool.propertyNameOf(DefinitionKind.Pipe);
const ngFactoryDefStatement = new o.ClassStmt(
/* name */ name,

View File

@ -325,7 +325,7 @@ export function compileDirectiveFromRender2(
const meta = directiveMetadataFromGlobalMetadata(directive, outputCtx, reflector);
const res = compileDirectiveFromMetadata(meta, outputCtx.constantPool, bindingParser);
const factoryRes = compileFactoryFromMetadata(meta);
const factoryRes = compileFactoryFromMetadata({...meta, injectFn: R3.directiveInject});
const ngFactoryDefStatement = new o.ClassStmt(
name, null,
[new o.ClassField(
@ -378,7 +378,7 @@ export function compileComponentFromRender2(
i18nUseExternalIds: true,
};
const res = compileComponentFromMetadata(meta, outputCtx.constantPool, bindingParser);
const factoryRes = compileFactoryFromMetadata(meta);
const factoryRes = compileFactoryFromMetadata({...meta, injectFn: R3.directiveInject});
const ngFactoryDefStatement = new o.ClassStmt(
name, null,
[new o.ClassField(