refactor(compiler): remove `R3ResolvedDependencyType` altogether (#41231)

Now that other values were removed from `R3ResolvedDependencyType`,
its meaning can now be inferred from the other properties in the
`R3DeclareDependencyMetadata` type. This commit removes this enum
and updates the code to work without it.

PR Close #41231
This commit is contained in:
Pete Bacon Darwin 2021-03-23 15:14:53 +00:00 committed by Alex Rickabaugh
parent 463111f6f9
commit 72b65f995d
31 changed files with 219 additions and 317 deletions

View File

@ -5,7 +5,7 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {compileFactoryFunction, ConstantPool, R3DeclareFactoryMetadata, R3DependencyMetadata, R3FactoryMetadata, R3FactoryTarget, R3PartialDeclaration, R3ResolvedDependencyType} from '@angular/compiler';
import {compileFactoryFunction, ConstantPool, R3DeclareDependencyMetadata, R3DeclareFactoryMetadata, R3DependencyMetadata, R3FactoryMetadata, R3FactoryTarget, R3PartialDeclaration} from '@angular/compiler';
import * as o from '@angular/compiler/src/output/output_ast';
import {AstObject} from '../../ast/ast_value';
@ -39,18 +39,14 @@ export function toR3FactoryMeta<TExpression>(
typeExpr.expression, 'Unsupported type, its name could not be determined');
}
const deps = getDeps(metaObj, 'deps');
const meta: R3FactoryMetadata = {
return {
name: typeName,
type: wrapReference(typeExpr.getOpaque()),
internalType: metaObj.getOpaque('type'),
typeArgumentCount: 0,
target: parseEnum(metaObj.getValue('target'), R3FactoryTarget),
deps,
deps: getDeps(metaObj, 'deps'),
};
return meta;
}
function getDeps<TExpression>(
@ -69,15 +65,24 @@ function getDeps<TExpression>(
return null;
}
function getDep<TExpression>(dep: AstObject<R3DependencyMetadata, TExpression>):
function getDep<TExpression>(depObj: AstObject<R3DeclareDependencyMetadata, TExpression>):
R3DependencyMetadata {
return {
token: dep.getOpaque('token'),
attribute: null,
resolved: parseEnum(dep.getValue('resolved'), R3ResolvedDependencyType),
host: dep.has('host') && dep.getBoolean('host'),
optional: dep.has('optional') && dep.getBoolean('optional'),
self: dep.has('self') && dep.getBoolean('self'),
skipSelf: dep.has('skipSelf') && dep.getBoolean('skipSelf'),
const isAttribute = depObj.has('attribute') && depObj.getBoolean('attribute');
const token = depObj.getOpaque('token');
// Normally `attribute` is a string literal and so its `attributeNameType` is the same string
// literal. If the `attribute` is some other expression, the `attributeNameType` would be the
// `unknown` type. It is not possible to generate this when linking, since it only deals with JS
// and not typings. When linking the existence of the `attributeNameType` only acts as a marker to
// change the injection instruction that is generated, so we just pass the literal string
// `"unknown"`.
const attributeNameType = isAttribute ? o.literal('unknown') : null;
const dep: R3DependencyMetadata = {
token,
attributeNameType,
host: depObj.has('host') && depObj.getBoolean('host'),
optional: depObj.has('optional') && depObj.getBoolean('optional'),
self: depObj.has('self') && depObj.getBoolean('self'),
skipSelf: depObj.has('skipSelf') && depObj.getBoolean('skipSelf'),
};
return dep;
}

View File

@ -384,7 +384,7 @@ runInEachFileSystem(() => {
expect(jsContents).toContain('__spreadArray([], __read(arguments))');
expect(jsContents)
.toContain(
'var ɵSubClass_BaseFactory = /*@__PURE__*/ ɵngcc0.ɵɵgetInheritedFactory(SubClass);');
'var ɵSubClass_BaseFactory; return function SubClass_Factory(t) { return (ɵSubClass_BaseFactory || (ɵSubClass_BaseFactory = ɵngcc0.ɵɵgetInheritedFactory(SubClass)))(t || SubClass); };');
});
it(`should be able to detect synthesized constructors in ES5 with downlevelIteration enabled (emitted helpers)`,
@ -423,7 +423,7 @@ runInEachFileSystem(() => {
expect(jsContents).toContain('__spreadArray([], __read(arguments))');
expect(jsContents)
.toContain(
'var ɵSubClass_BaseFactory = /*@__PURE__*/ ɵngcc0.ɵɵgetInheritedFactory(SubClass);');
'var ɵSubClass_BaseFactory; return function SubClass_Factory(t) { return (ɵSubClass_BaseFactory || (ɵSubClass_BaseFactory = ɵngcc0.ɵɵgetInheritedFactory(SubClass)))(t || SubClass); };');
});
it('should not add `const` in ES5 generated code', () => {

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {compileComponentFromMetadata, compileDeclareComponentFromMetadata, ConstantPool, CssSelector, DeclarationListEmitMode, DEFAULT_INTERPOLATION_CONFIG, DomElementSchemaRegistry, Expression, ExternalExpr, Identifiers, InterpolationConfig, LexerRange, makeBindingParser, ParsedTemplate, ParseSourceFile, parseTemplate, R3CompiledExpression, R3ComponentMetadata, R3FactoryMetadata, R3FactoryTarget, R3TargetBinder, R3UsedDirectiveMetadata, SelectorMatcher, Statement, TmplAstNode, WrappedNodeExpr} from '@angular/compiler';
import {compileComponentFromMetadata, compileDeclareComponentFromMetadata, ConstantPool, CssSelector, DeclarationListEmitMode, DEFAULT_INTERPOLATION_CONFIG, DomElementSchemaRegistry, Expression, ExternalExpr, InterpolationConfig, LexerRange, makeBindingParser, ParsedTemplate, ParseSourceFile, parseTemplate, R3ComponentMetadata, R3FactoryMetadata, R3FactoryTarget, R3TargetBinder, R3UsedDirectiveMetadata, SelectorMatcher, Statement, TmplAstNode, WrappedNodeExpr} from '@angular/compiler';
import * as ts from 'typescript';
import {Cycle, CycleAnalyzer, CycleHandlingStrategy} from '../../cycles';

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {compileDeclareDirectiveFromMetadata, compileDirectiveFromMetadata, ConstantPool, Expression, ExternalExpr, getSafePropertyAccessString, Identifiers, makeBindingParser, ParsedHostBindings, ParseError, parseHostBindings, R3CompiledExpression, R3DependencyMetadata, R3DirectiveMetadata, R3FactoryMetadata, R3FactoryTarget, R3QueryMetadata, R3ResolvedDependencyType, Statement, verifyHostBindings, WrappedNodeExpr} from '@angular/compiler';
import {compileDeclareDirectiveFromMetadata, compileDirectiveFromMetadata, ConstantPool, Expression, ExternalExpr, getSafePropertyAccessString, makeBindingParser, ParsedHostBindings, ParseError, parseHostBindings, R3DirectiveMetadata, R3FactoryMetadata, R3FactoryTarget, R3QueryMetadata, Statement, verifyHostBindings, WrappedNodeExpr} from '@angular/compiler';
import {emitDistinctChangesOnlyDefaultValue} from '@angular/compiler/src/core';
import * as ts from 'typescript';
@ -468,27 +468,19 @@ export function extractDirectiveMetadata(
}
const rawCtorDeps = getConstructorDependencies(clazz, reflector, defaultImportRecorder, isCore);
let ctorDeps: R3DependencyMetadata[]|'invalid'|null;
// Non-abstract directives (those with a selector) require valid constructor dependencies, whereas
// abstract directives are allowed to have invalid dependencies, given that a subclass may call
// the constructor explicitly.
if (selector !== null) {
ctorDeps = validateConstructorDependencies(clazz, rawCtorDeps);
} else {
ctorDeps = unwrapConstructorDependencies(rawCtorDeps);
}
const ctorDeps = selector !== null ? validateConstructorDependencies(clazz, rawCtorDeps) :
unwrapConstructorDependencies(rawCtorDeps);
const isStructural = ctorDeps !== null && ctorDeps !== 'invalid' && ctorDeps.some(dep => {
if (dep.resolved !== R3ResolvedDependencyType.Token || !(dep.token instanceof ExternalExpr)) {
return false;
}
if (dep.token.value.moduleName !== '@angular/core' || dep.token.value.name !== 'TemplateRef') {
return false;
}
return true;
});
// Structural directives must have a `TemplateRef` dependency.
const isStructural = ctorDeps !== null && ctorDeps !== 'invalid' &&
ctorDeps.some(
dep => (dep.token instanceof ExternalExpr) &&
dep.token.value.moduleName === '@angular/core' &&
dep.token.value.name === 'TemplateRef');
// Detect if the component inherits from another class
const usesInheritance = reflector.hasBaseClass(clazz);

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {compileInjectable as compileIvyInjectable, Expression, LiteralExpr, R3DependencyMetadata, R3FactoryMetadata, R3FactoryTarget, R3InjectableMetadata, R3ResolvedDependencyType, Statement, WrappedNodeExpr} from '@angular/compiler';
import {compileInjectable as compileIvyInjectable, Expression, LiteralExpr, R3DependencyMetadata, R3FactoryMetadata, R3FactoryTarget, R3InjectableMetadata, Statement, WrappedNodeExpr} from '@angular/compiler';
import * as ts from 'typescript';
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
@ -320,9 +320,8 @@ function extractInjectableCtorDeps(
function getDep(dep: ts.Expression, reflector: ReflectionHost): R3DependencyMetadata {
const meta: R3DependencyMetadata = {
token: new WrappedNodeExpr(dep),
attribute: null,
attributeNameType: null,
host: false,
resolved: R3ResolvedDependencyType.Token,
optional: false,
self: false,
skipSelf: false,

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Expression, ExternalExpr, LiteralExpr, ParseLocation, ParseSourceFile, ParseSourceSpan, R3CompiledExpression, R3DependencyMetadata, R3Reference, R3ResolvedDependencyType, ReadPropExpr, Statement, WrappedNodeExpr} from '@angular/compiler';
import {Expression, ExternalExpr, LiteralExpr, ParseLocation, ParseSourceFile, ParseSourceSpan, R3CompiledExpression, R3DependencyMetadata, R3Reference, ReadPropExpr, Statement, WrappedNodeExpr} from '@angular/compiler';
import * as ts from 'typescript';
import {ErrorCode, FatalDiagnosticError, makeDiagnostic, makeRelatedInformation} from '../../diagnostics';
@ -44,9 +44,8 @@ export function getConstructorDependencies(
}
ctorParams.forEach((param, idx) => {
let token = valueReferenceToExpression(param.typeValueReference, defaultImportRecorder);
let attribute: Expression|null = null;
let attributeNameType: Expression|null = null;
let optional = false, self = false, skipSelf = false, host = false;
let resolved = R3ResolvedDependencyType.Token;
(param.decorators || []).filter(dec => isCore || isAngularCore(dec)).forEach(dec => {
const name = isCore || dec.import === null ? dec.name : dec.import!.name;
@ -74,11 +73,11 @@ export function getConstructorDependencies(
const attributeName = dec.args[0];
token = new WrappedNodeExpr(attributeName);
if (ts.isStringLiteralLike(attributeName)) {
attribute = new LiteralExpr(attributeName.text);
attributeNameType = new LiteralExpr(attributeName.text);
} else {
attribute = new WrappedNodeExpr(ts.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword));
attributeNameType =
new WrappedNodeExpr(ts.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword));
}
resolved = R3ResolvedDependencyType.Attribute;
} else {
throw new FatalDiagnosticError(
ErrorCode.DECORATOR_UNEXPECTED, Decorator.nodeForError(dec),
@ -97,7 +96,7 @@ export function getConstructorDependencies(
reason: param.typeValueReference.reason,
});
} else {
deps.push({token, attribute, optional, self, skipSelf, host, resolved});
deps.push({token, attributeNameType, optional, self, skipSelf, host});
}
});
if (errors.length === 0) {

View File

@ -43,7 +43,7 @@ import * as i0 from "@angular/core";
export class IfDirective {
constructor(template) { }
}
IfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: IfDirective, deps: [{ token: i0.TemplateRef, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Directive });
IfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: IfDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
IfDirective.ɵdir = i0.ɵɵngDeclareDirective({ version: "0.0.0-PLACEHOLDER", type: IfDirective, selector: "[if]", ngImport: i0 });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(IfDirective, [{
type: Directive,

View File

@ -156,7 +156,7 @@ export class MyPipe {
return value;
}
}
MyPipe.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyPipe, deps: [{ token: i0.ChangeDetectorRef, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Pipe });
MyPipe.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyPipe, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Pipe });
MyPipe.ɵpipe = i0.ɵɵngDeclarePipe({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyPipe, name: "myPipe" });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyPipe, [{
type: Pipe,
@ -168,7 +168,7 @@ export class MyOtherPipe {
return value;
}
}
MyOtherPipe.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyOtherPipe, deps: [{ token: i0.ChangeDetectorRef, resolved: i0.ɵɵResolvedDependencyType.Token, optional: true }], target: i0.ɵɵFactoryTarget.Pipe });
MyOtherPipe.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyOtherPipe, deps: [{ token: i0.ChangeDetectorRef, optional: true }], target: i0.ɵɵFactoryTarget.Pipe });
MyOtherPipe.ɵpipe = i0.ɵɵngDeclarePipe({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyOtherPipe, name: "myOtherPipe" });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyOtherPipe, [{
type: Pipe,

View File

@ -10,7 +10,7 @@ export class ForOfDirective {
}
ngOnChanges(simpleChanges) { }
}
ForOfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: ForOfDirective, deps: [{ token: i0.ViewContainerRef, resolved: i0.ɵɵResolvedDependencyType.Token }, { token: i0.TemplateRef, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Directive });
ForOfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: ForOfDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
ForOfDirective.ɵdir = i0.ɵɵngDeclareDirective({ version: "0.0.0-PLACEHOLDER", type: ForOfDirective, selector: "[forOf]", inputs: { forOf: "forOf" }, usesOnChanges: true, ngImport: i0 });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ForOfDirective, [{
type: Directive,
@ -101,7 +101,7 @@ export class ForOfDirective {
}
ngOnChanges(simpleChanges) { }
}
ForOfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: ForOfDirective, deps: [{ token: i0.ViewContainerRef, resolved: i0.ɵɵResolvedDependencyType.Token }, { token: i0.TemplateRef, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Directive });
ForOfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: ForOfDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
ForOfDirective.ɵdir = i0.ɵɵngDeclareDirective({ version: "0.0.0-PLACEHOLDER", type: ForOfDirective, selector: "[forOf]", inputs: { forOf: "forOf" }, usesOnChanges: true, ngImport: i0 });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ForOfDirective, [{
type: Directive,
@ -192,7 +192,7 @@ export class ForOfDirective {
}
ngOnChanges(simpleChanges) { }
}
ForOfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: ForOfDirective, deps: [{ token: i0.ViewContainerRef, resolved: i0.ɵɵResolvedDependencyType.Token }, { token: i0.TemplateRef, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Directive });
ForOfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: ForOfDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
ForOfDirective.ɵdir = i0.ɵɵngDeclareDirective({ version: "0.0.0-PLACEHOLDER", type: ForOfDirective, selector: "[forOf]", inputs: { forOf: "forOf" }, usesOnChanges: true, ngImport: i0 });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ForOfDirective, [{
type: Directive,
@ -309,7 +309,7 @@ export class ForOfDirective {
}
ngOnChanges(simpleChanges) { }
}
ForOfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: ForOfDirective, deps: [{ token: i0.ViewContainerRef, resolved: i0.ɵɵResolvedDependencyType.Token }, { token: i0.TemplateRef, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Directive });
ForOfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: ForOfDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
ForOfDirective.ɵdir = i0.ɵɵngDeclareDirective({ version: "0.0.0-PLACEHOLDER", type: ForOfDirective, selector: "[forOf]", inputs: { forOf: "forOf" }, usesOnChanges: true, ngImport: i0 });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ForOfDirective, [{
type: Directive,

View File

@ -206,7 +206,7 @@ export class MyComponent {
this.cdr = cdr;
}
}
MyComponent.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyComponent, deps: [{ token: i0.ElementRef, resolved: i0.ɵɵResolvedDependencyType.Token }, { token: i0.ViewContainerRef, resolved: i0.ɵɵResolvedDependencyType.Token }, { token: i0.ChangeDetectorRef, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Component });
MyComponent.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyComponent, deps: [{ token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyComponent, selector: "my-component", ngImport: i0, template: '', isInline: true });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyComponent, [{
type: Component,
@ -249,7 +249,7 @@ import * as i0 from "@angular/core";
export class IfDirective {
constructor(template) { }
}
IfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: IfDirective, deps: [{ token: i0.TemplateRef, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Directive });
IfDirective.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: IfDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
IfDirective.ɵdir = i0.ɵɵngDeclareDirective({ version: "0.0.0-PLACEHOLDER", type: IfDirective, selector: "[if]", ngImport: i0 });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(IfDirective, [{
type: Directive,

View File

@ -177,7 +177,7 @@ export class BaseService {
}
;
}
BaseService.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: BaseService, deps: [{ token: Thing, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Injectable });
BaseService.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: BaseService, deps: [{ token: Thing }], target: i0.ɵɵFactoryTarget.Injectable });
BaseService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: BaseService, factory: BaseService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BaseService, [{
type: Injectable
@ -478,7 +478,7 @@ export class BaseModule {
this.service = service;
}
}
BaseModule.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: BaseModule, deps: [{ token: Service, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.NgModule });
BaseModule.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: BaseModule, deps: [{ token: Service }], target: i0.ɵɵFactoryTarget.NgModule });
BaseModule.ɵmod = i0.ɵɵngDeclareNgModule({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: BaseModule });
BaseModule.ɵinj = i0.ɵɵngDeclareInjector({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: BaseModule, providers: [Service] });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BaseModule, [{

View File

@ -10,10 +10,13 @@ MyService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MyService, fac
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyService, [{
type: Injectable
}], null, null); })();
export class MyComponent {
constructor(name, s1, s2, s4, s3, s5, s6) { }
function dynamicAttrName() {
return 'the-attr';
}
MyComponent.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyComponent, deps: [{ token: 'name', resolved: i0.ɵɵResolvedDependencyType.Attribute }, { token: MyService, resolved: i0.ɵɵResolvedDependencyType.Token }, { token: MyService, resolved: i0.ɵɵResolvedDependencyType.Token, host: true }, { token: MyService, resolved: i0.ɵɵResolvedDependencyType.Token, self: true }, { token: MyService, resolved: i0.ɵɵResolvedDependencyType.Token, skipSelf: true }, { token: MyService, resolved: i0.ɵɵResolvedDependencyType.Token, optional: true }, { token: MyService, resolved: i0.ɵɵResolvedDependencyType.Token, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
export class MyComponent {
constructor(name, other, s1, s2, s4, s3, s5, s6) { }
}
MyComponent.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyComponent, deps: [{ token: 'name', attribute: true }, { token: dynamicAttrName(), attribute: true }, { token: MyService }, { token: MyService, host: true }, { token: MyService, self: true }, { token: MyService, skipSelf: true }, { token: MyService, optional: true }, { token: MyService, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", type: MyComponent, selector: "my-component", ngImport: i0, template: ``, isInline: true });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyComponent, [{
type: Component,
@ -21,6 +24,9 @@ MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: "0.0.0-PLACEHOLDER", ty
}], function () { return [{ type: undefined, decorators: [{
type: Attribute,
args: ['name']
}] }, { type: undefined, decorators: [{
type: Attribute,
args: [dynamicAttrName()]
}] }, { type: MyService }, { type: MyService, decorators: [{
type: Host
}] }, { type: MyService, decorators: [{
@ -53,8 +59,8 @@ export declare class MyService {
static ɵprov: i0.ɵɵInjectableDef<MyService>;
}
export declare class MyComponent {
constructor(name: string, s1: MyService, s2: MyService, s4: MyService, s3: MyService, s5: MyService, s6: MyService);
static ɵfac: i0.ɵɵFactoryDeclaration<MyComponent, [{ attribute: "name"; }, null, { host: true; }, { self: true; }, { skipSelf: true; }, { optional: true; }, { optional: true; self: true; }]>;
constructor(name: string, other: string, s1: MyService, s2: MyService, s4: MyService, s3: MyService, s5: MyService, s6: MyService);
static ɵfac: i0.ɵɵFactoryDeclaration<MyComponent, [{ attribute: "name"; }, { attribute: unknown; }, null, { host: true; }, { self: true; }, { skipSelf: true; }, { optional: true; }, { optional: true; self: true; }]>;
static ɵcmp: i0.ɵɵComponentDeclaration<MyComponent, "my-component", never, {}, {}, never, never>;
}
export declare class MyModule {
@ -73,7 +79,7 @@ class MyDependency {
export class MyService {
constructor(dep) { }
}
MyService.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyService, deps: [{ token: MyDependency, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Injectable });
MyService.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyService, deps: [{ token: MyDependency }], target: i0.ɵɵFactoryTarget.Injectable });
MyService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MyService, factory: MyService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyService, [{
type: Injectable
@ -104,7 +110,7 @@ class MyOptionalDependency {
export class MyService {
constructor(dep, optionalDep) { }
}
MyService.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyService, deps: [{ token: MyDependency, resolved: i0.ɵɵResolvedDependencyType.Token }, { token: MyOptionalDependency, resolved: i0.ɵɵResolvedDependencyType.Token, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
MyService.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyService, deps: [{ token: MyDependency }, { token: MyOptionalDependency, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
MyService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MyService, factory: MyService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyService, [{
type: Injectable
@ -296,7 +302,7 @@ export class MyPipe {
return value;
}
}
MyPipe.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyPipe, deps: [{ token: Service, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Pipe });
MyPipe.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyPipe, deps: [{ token: Service }], target: i0.ɵɵFactoryTarget.Pipe });
MyPipe.ɵpipe = i0.ɵɵngDeclarePipe({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyPipe, name: "myPipe" });
MyPipe.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MyPipe, factory: MyPipe.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyPipe, [{
@ -311,7 +317,7 @@ export class MyOtherPipe {
return value;
}
}
MyOtherPipe.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyOtherPipe, deps: [{ token: Service, resolved: i0.ɵɵResolvedDependencyType.Token }], target: i0.ɵɵFactoryTarget.Pipe });
MyOtherPipe.ɵfac = i0.ɵɵngDeclareFactory({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyOtherPipe, deps: [{ token: Service }], target: i0.ɵɵFactoryTarget.Pipe });
MyOtherPipe.ɵpipe = i0.ɵɵngDeclarePipe({ version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyOtherPipe, name: "myOtherPipe" });
MyOtherPipe.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: MyOtherPipe, factory: MyOtherPipe.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MyOtherPipe, [{

View File

@ -2,6 +2,7 @@
MyComponent.ɵfac = function MyComponent_Factory(t) {
return new (t || MyComponent)(
$r3$.ɵɵinjectAttribute('name'),
$r3$.ɵɵinjectAttribute(dynamicAttrName()),
$r3$.ɵɵdirectiveInject(MyService),
$r3$.ɵɵdirectiveInject(MyService, 1),
$r3$.ɵɵdirectiveInject(MyService, 2),

View File

@ -4,10 +4,15 @@ import {Attribute, Component, Host, Injectable, NgModule, Optional, Self, SkipSe
export class MyService {
}
function dynamicAttrName() {
return 'the-attr';
}
@Component({selector: 'my-component', template: ``})
export class MyComponent {
constructor(
@Attribute('name') name: string,
@Attribute(dynamicAttrName()) other: string,
s1: MyService,
@Host() s2: MyService,
@Self() s4: MyService,

View File

@ -25,6 +25,10 @@ describe('compiler compliance: dependency injection', () => {
@Injectable()
export class MyService {}
function dynamicAttrName() {
return 'the-attr';
}
@Component({
selector: 'my-component',
template: \`\`
@ -32,6 +36,7 @@ describe('compiler compliance: dependency injection', () => {
export class MyComponent {
constructor(
@Attribute('name') name:string,
@Attribute(dynamicAttrName()) other: string,
s1: MyService,
@Host() s2: MyService,
@Self() s4: MyService,
@ -51,6 +56,7 @@ describe('compiler compliance: dependency injection', () => {
MyComponent.ɵfac = function MyComponent_Factory(t) {
return new (t || MyComponent)(
$r3$.ɵɵinjectAttribute('name'),
$r3$.ɵɵinjectAttribute(dynamicAttrName()),
$r3$.ɵɵdirectiveInject(MyService),
$r3$.ɵɵdirectiveInject(MyService, 1),
$r3$.ɵɵdirectiveInject(MyService, 2),

View File

@ -97,7 +97,7 @@ export {BoundAttribute as TmplAstBoundAttribute, BoundEvent as TmplAstBoundEvent
export * from './render3/view/t2_api';
export * from './render3/view/t2_binder';
export {Identifiers as R3Identifiers} from './render3/r3_identifiers';
export {compileFactoryFunction, R3DependencyMetadata, R3FactoryMetadata, R3FactoryTarget, R3ResolvedDependencyType} from './render3/r3_factory';
export {compileFactoryFunction, R3DependencyMetadata, R3FactoryMetadata, R3FactoryTarget} from './render3/r3_factory';
export {compileNgModule, R3NgModuleMetadata} from './render3/r3_module_compiler';
export {compileInjector, R3InjectorMetadata} from './render3/r3_injector_compiler';
export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler';

View File

@ -60,7 +60,6 @@ export interface CompilerFacade {
createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan;
R3ResolvedDependencyType: typeof R3ResolvedDependencyType;
R3FactoryTarget: typeof R3FactoryTarget;
ResourceLoader: {new(): ResourceLoader};
}
@ -83,12 +82,6 @@ export type StringMapWithRename = {
export type Provider = any;
export enum R3ResolvedDependencyType {
Token = 0,
Attribute = 1,
Invalid = 2,
}
export enum R3FactoryTarget {
Directive = 0,
Component = 1,
@ -98,17 +91,17 @@ export enum R3FactoryTarget {
}
export interface R3DependencyMetadataFacade {
token: any;
resolved: R3ResolvedDependencyType;
token: unknown;
attribute: string|null;
host: boolean;
optional: boolean;
self: boolean;
skipSelf?: boolean;
skipSelf: boolean;
}
export interface R3DeclareDependencyMetadataFacade {
token: any;
resolved: R3ResolvedDependencyType;
token: unknown;
attribute?: boolean;
host?: boolean;
optional?: boolean;
self?: boolean;
@ -118,9 +111,7 @@ export interface R3DeclareDependencyMetadataFacade {
export interface R3PipeMetadataFacade {
name: string;
type: any;
typeArgumentCount: number;
pipeName: string;
deps: R3DependencyMetadataFacade[]|null;
pure: boolean;
}
@ -156,9 +147,7 @@ export interface R3InjectorMetadataFacade {
export interface R3DirectiveMetadataFacade {
name: string;
type: any;
typeArgumentCount: number;
typeSourceSpan: ParseSourceSpan;
deps: R3DependencyMetadataFacade[]|null;
selector: string|null;
queries: R3QueryMetadataFacade[];
host: {[key: string]: string};

View File

@ -10,18 +10,17 @@
import {CompilerFacade, CoreEnvironment, ExportedCompilerFacade, OpaqueValue, R3ComponentMetadataFacade, R3DeclareComponentFacade, R3DeclareDependencyMetadataFacade, R3DeclareDirectiveFacade, R3DeclareFactoryFacade, R3DeclareInjectorFacade, R3DeclareNgModuleFacade, R3DeclarePipeFacade, R3DeclareQueryMetadataFacade, R3DependencyMetadataFacade, R3DirectiveMetadataFacade, R3FactoryDefMetadataFacade, R3InjectableMetadataFacade, R3InjectorMetadataFacade, R3NgModuleMetadataFacade, R3PipeMetadataFacade, R3QueryMetadataFacade, StringMap, StringMapWithRename} from './compiler_facade_interface';
import {ConstantPool} from './constant_pool';
import {ChangeDetectionStrategy, HostBinding, HostListener, Input, Output, Type, ViewEncapsulation} from './core';
import {Identifiers} from './identifiers';
import {compileInjectable} from './injectable_compiler_2';
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './ml_parser/interpolation_config';
import {DeclareVarStmt, Expression, LiteralExpr, Statement, StmtModifier, WrappedNodeExpr} from './output/output_ast';
import {DeclareVarStmt, Expression, literal, LiteralExpr, Statement, StmtModifier, WrappedNodeExpr} from './output/output_ast';
import {JitEvaluator} from './output/output_jit';
import {ParseError, ParseSourceSpan, r3JitTypeSourceSpan} from './parse_util';
import {compileFactoryFunction, R3DependencyMetadata, R3FactoryTarget, R3ResolvedDependencyType} from './render3/r3_factory';
import {compileFactoryFunction, R3DependencyMetadata, R3FactoryTarget} from './render3/r3_factory';
import {compileInjector, R3InjectorMetadata} from './render3/r3_injector_compiler';
import {R3JitReflector} from './render3/r3_jit';
import {compileNgModule, compileNgModuleDeclarationExpression, R3NgModuleMetadata} from './render3/r3_module_compiler';
import {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler';
import {getSafePropertyAccessString, R3Reference, wrapReference} from './render3/util';
import {getSafePropertyAccessString, wrapReference} from './render3/util';
import {DeclarationListEmitMode, R3ComponentMetadata, R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata, R3UsedDirectiveMetadata} from './render3/view/api';
import {compileComponentFromMetadata, compileDirectiveFromMetadata, ParsedHostBindings, parseHostBindings, verifyHostBindings} from './render3/view/compiler';
import {makeBindingParser, parseTemplate} from './render3/view/template';
@ -29,7 +28,6 @@ import {ResourceLoader} from './resource_loader';
import {DomElementSchemaRegistry} from './schema/dom_element_schema_registry';
export class CompilerFacadeImpl implements CompilerFacade {
R3ResolvedDependencyType = R3ResolvedDependencyType as any;
R3FactoryTarget = R3FactoryTarget as any;
ResourceLoader = ResourceLoader;
private elementSchemaRegistry = new DomElementSchemaRegistry();
@ -42,8 +40,8 @@ export class CompilerFacadeImpl implements CompilerFacade {
name: facade.name,
type: wrapReference(facade.type),
internalType: new WrappedNodeExpr(facade.type),
typeArgumentCount: facade.typeArgumentCount,
deps: convertR3DependencyMetadataArray(facade.deps),
typeArgumentCount: 0,
deps: null,
pipeName: facade.pipeName,
pure: facade.pure,
};
@ -220,7 +218,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
type: wrapReference(meta.type),
internalType: new WrappedNodeExpr(meta.type),
typeArgumentCount: 0,
deps: convertR3DeclareDependencyMetadataArray(meta.deps),
deps: meta.deps && meta.deps.map(convertR3DeclareDependencyMetadata),
target: meta.target,
});
return this.jitExpression(
@ -314,10 +312,11 @@ function convertDirectiveFacadeToMetadata(facade: R3DirectiveMetadataFacade): R3
return {
...facade as R3DirectiveMetadataFacadeNoPropAndWhitespace,
typeArgumentCount: 0,
typeSourceSpan: facade.typeSourceSpan,
type: wrapReference(facade.type),
internalType: new WrappedNodeExpr(facade.type),
deps: convertR3DependencyMetadataArray(facade.deps),
deps: null,
host: extractHostBindings(facade.propMetadata, facade.typeSourceSpan, facade.host),
inputs: {...inputsFromMetadata, ...inputsFromType},
outputs: {...outputsFromMetadata, ...outputsFromType},
@ -462,35 +461,38 @@ function computeProvidedIn(providedIn: Type|string|null|undefined): Expression {
}
}
function convertR3DependencyMetadata(facade: R3DeclareDependencyMetadataFacade):
R3DependencyMetadata {
let tokenExpr;
if (facade.token === null) {
tokenExpr = new LiteralExpr(null);
} else if (facade.resolved === R3ResolvedDependencyType.Attribute) {
tokenExpr = new LiteralExpr(facade.token);
} else {
tokenExpr = new WrappedNodeExpr(facade.token);
}
return {
token: tokenExpr,
attribute: null,
resolved: facade.resolved,
host: !!facade.host,
optional: !!facade.optional,
self: !!facade.self,
skipSelf: !!facade.skipSelf,
};
}
function convertR3DependencyMetadataArray(facades: R3DependencyMetadataFacade[]|null|
undefined): R3DependencyMetadata[]|null {
return facades == null ? null : facades.map(convertR3DependencyMetadata);
}
function convertR3DeclareDependencyMetadataArray(facades: R3DeclareDependencyMetadataFacade[]|null|
undefined): R3DependencyMetadata[]|null {
return facades == null ? null : facades.map(convertR3DependencyMetadata);
function convertR3DependencyMetadata(facade: R3DependencyMetadataFacade): R3DependencyMetadata {
const isAttributeDep = facade.attribute != null; // both `null` and `undefined`
const rawToken = facade.token === null ? null : new WrappedNodeExpr(facade.token);
// In JIT mode, if the dep is an `@Attribute()` then we use the attribute name given in
// `attribute` rather than the `token`.
const token = isAttributeDep ? new WrappedNodeExpr(facade.attribute) : rawToken;
return createR3DependencyMetadata(
token, isAttributeDep, facade.host, facade.optional, facade.self, facade.skipSelf);
}
function convertR3DeclareDependencyMetadata(facade: R3DeclareDependencyMetadataFacade):
R3DependencyMetadata {
const isAttributeDep = facade.attribute ?? false;
const token = facade.token === null ? null : new WrappedNodeExpr(facade.token);
return createR3DependencyMetadata(
token, isAttributeDep, facade.host ?? false, facade.optional ?? false, facade.self ?? false,
facade.skipSelf ?? false);
}
function createR3DependencyMetadata(
token: WrappedNodeExpr<unknown>|null, isAttributeDep: boolean, host: boolean, optional: boolean,
self: boolean, skipSelf: boolean): R3DependencyMetadata {
// If the dep is an `@Attribute()` the `attributeNameType` ought to be the `unknown` type.
// But types are not available at runtime so we just use a literal `"<unknown>"` string as a dummy
// marker.
const attributeNameType = isAttributeDep ? literal('unknown') : null;
return {token, attributeNameType, host, optional, self, skipSelf};
}
function extractHostBindings(

View File

@ -343,14 +343,15 @@ export interface R3DeclarePipeMetadata extends R3PartialDeclaration {
*/
export interface R3DeclareFactoryMetadata extends R3PartialDeclaration {
/**
* Regardless of whether `fnOrClass` is a constructor function or a user-defined factory, it
* may have 0 or more parameters, which will be injected according to the `R3DependencyMetadata`
* for those parameters. If this is `null`, then the type's constructor is nonexistent and will
* be inherited from `fnOrClass` which is interpreted as the current type. If this is `'invalid'`,
* then one or more of the parameters wasn't resolvable and any attempt to use these deps will
* result in a runtime error.
* A collection of dependencies that this factory relies upon.
*
* If this is `null`, then the type's constructor is nonexistent and will be inherited from an
* ancestor of the type.
*
* If this is `'invalid'`, then one or more of the parameters wasn't resolvable and any attempt to
* use these deps will result in a runtime error.
*/
deps: R3DependencyMetadata[]|'invalid'|null;
deps: R3DeclareDependencyMetadata[]|'invalid'|null;
/**
* Type of the target being created by the factory.
@ -358,11 +359,6 @@ export interface R3DeclareFactoryMetadata extends R3PartialDeclaration {
target: R3FactoryTarget;
}
export enum R3FactoryDelegateType {
Class = 0,
Function = 1,
}
export enum R3FactoryTarget {
Directive = 0,
Component = 1,
@ -372,19 +368,23 @@ export enum R3FactoryTarget {
}
/**
* Metadata representing a single dependency to be injected into a constructor or function call.
* Metadata indicating how a dependency should be injected into a factory.
*/
export interface R3DependencyMetadata {
export interface R3DeclareDependencyMetadata {
/**
* An expression representing the token or value to be injected.
* An expression representing the token or value to be injected, or `null` if the dependency is
* not valid.
*
* If this dependency is due to the `@Attribute()` decorator, then this is an expression
* evaluating to the name of the attribute.
*/
token: o.Expression;
token: o.Expression|null;
/**
* An enum indicating whether this dependency has special meaning to Angular and needs to be
* injected specially.
* Whether the dependency is injecting an attribute value.
* Default: false.
*/
resolved: R3ResolvedDependencyType;
attribute?: boolean;
/**
* Whether the dependency has an @Host qualifier.
@ -410,30 +410,3 @@ export interface R3DependencyMetadata {
*/
skipSelf?: boolean;
}
/**
* Resolved type of a dependency.
*
* Occasionally, dependencies will have special significance which is known statically. In that
* case the `R3ResolvedDependencyType` informs the factory generator that a particular dependency
* should be generated specially (usually by calling a special injection function instead of the
* standard one).
*/
export enum R3ResolvedDependencyType {
/**
* A normal token dependency.
*/
Token = 0,
/**
* The dependency is for an attribute.
*
* The token expression is a string representing the attribute name.
*/
Attribute = 1,
/**
* An invalid dependency (no token could be determined). An error should be thrown at runtime.
*/
Invalid = 2,
}

View File

@ -6,12 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as o from '../../output/output_ast';
import {createFactoryType, R3FactoryMetadata, R3FactoryTarget, R3ResolvedDependencyType} from '../r3_factory';
import {createFactoryType, R3DependencyMetadata, R3FactoryMetadata, R3FactoryTarget} from '../r3_factory';
import {Identifiers as R3} from '../r3_identifiers';
import {R3CompiledExpression} from '../util';
import {DefinitionMap} from '../view/util';
import {R3DeclareFactoryMetadata, R3DependencyMetadata} from './api';
import {R3DeclareDependencyMetadata, R3DeclareFactoryMetadata} from './api';
export function compileDeclareFactoryFunction(meta: R3FactoryMetadata): R3CompiledExpression {
const definitionMap = new DefinitionMap<R3DeclareFactoryMetadata>();
@ -40,22 +40,22 @@ function compileDependencies(deps: R3DependencyMetadata[]|'invalid'|null): o.Lit
}
function compileDependency(dep: R3DependencyMetadata): o.LiteralMapExpr {
const depMeta = new DefinitionMap<R3DependencyMetadata>();
const depMeta = new DefinitionMap<R3DeclareDependencyMetadata>();
depMeta.set('token', dep.token);
depMeta.set(
'resolved',
o.importExpr(R3.R3ResolvedDependencyType).prop(R3ResolvedDependencyType[dep.resolved]));
if (dep.attributeNameType !== null) {
depMeta.set('attribute', o.literal(true));
}
if (dep.host) {
depMeta.set('host', o.literal(dep.host));
depMeta.set('host', o.literal(true));
}
if (dep.optional) {
depMeta.set('optional', o.literal(dep.optional));
depMeta.set('optional', o.literal(true));
}
if (dep.self) {
depMeta.set('self', o.literal(dep.self));
depMeta.set('self', o.literal(true));
}
if (dep.skipSelf) {
depMeta.set('skipSelf', o.literal(dep.skipSelf));
depMeta.set('skipSelf', o.literal(true));
}
return depMeta.toLiteralMap();
}

View File

@ -8,9 +8,7 @@
import {StaticSymbol} from '../aot/static_symbol';
import {CompileTypeMetadata, tokenReference} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector';
import {InjectFlags} from '../core';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
import {Identifiers as R3} from '../render3/r3_identifiers';
import {OutputContext} from '../util';
@ -88,54 +86,19 @@ export enum R3FactoryTarget {
NgModule = 4,
}
/**
* Resolved type of a dependency.
*
* Occasionally, dependencies will have special significance which is known statically. In that
* case the `R3ResolvedDependencyType` informs the factory generator that a particular dependency
* should be generated specially (usually by calling a special injection function instead of the
* standard one).
*/
export enum R3ResolvedDependencyType {
/**
* A normal token dependency.
*/
Token = 0,
/**
* The dependency is for an attribute.
*
* The token expression is a string representing the attribute name.
*/
Attribute = 1,
/**
* An invalid dependency (no token could be determined). An error should be thrown at runtime.
*/
Invalid = 2,
}
/**
* Metadata representing a single dependency to be injected into a constructor or function call.
*/
export interface R3DependencyMetadata {
/**
* An expression representing the token or value to be injected.
* Or `null` if the dependency could not be resolved - making it invalid.
*/
token: o.Expression;
token: o.Expression|null;
/**
* If an @Attribute decorator is present, this is the literal type of the attribute name, or
* the unknown type if no literal type is available (e.g. the attribute name is an expression).
* Will be null otherwise.
* Otherwise it is null;
*/
attribute: o.Expression|null;
/**
* An enum indicating whether this dependency has special meaning to Angular and needs to be
* injected specially.
*/
resolved: R3ResolvedDependencyType;
attributeNameType: o.Expression|null;
/**
* Whether the dependency has an @Host qualifier.
@ -266,35 +229,37 @@ function injectDependencies(deps: R3DependencyMetadata[], target: R3FactoryTarge
function compileInjectDependency(
dep: R3DependencyMetadata, target: R3FactoryTarget, index: number): o.Expression {
// Interpret the dependency according to its resolved type.
switch (dep.resolved) {
case R3ResolvedDependencyType.Token:
// Build up the injection flags according to the metadata.
const flags = InjectFlags.Default | (dep.self ? InjectFlags.Self : 0) |
(dep.skipSelf ? InjectFlags.SkipSelf : 0) | (dep.host ? InjectFlags.Host : 0) |
(dep.optional ? InjectFlags.Optional : 0) |
(target === R3FactoryTarget.Pipe ? InjectFlags.ForPipe : 0);
if (dep.token === null) {
return o.importExpr(R3.invalidFactoryDep).callFn([o.literal(index)]);
} else if (dep.attributeNameType === null) {
// Build up the injection flags according to the metadata.
const flags = InjectFlags.Default | (dep.self ? InjectFlags.Self : 0) |
(dep.skipSelf ? InjectFlags.SkipSelf : 0) | (dep.host ? InjectFlags.Host : 0) |
(dep.optional ? InjectFlags.Optional : 0) |
(target === R3FactoryTarget.Pipe ? InjectFlags.ForPipe : 0);
// If this dependency is optional or otherwise has non-default flags, then additional
// parameters describing how to inject the dependency must be passed to the inject function
// that's being used.
let flagsParam: o.LiteralExpr|null =
(flags !== InjectFlags.Default || dep.optional) ? o.literal(flags) : null;
// If this dependency is optional or otherwise has non-default flags, then additional
// parameters describing how to inject the dependency must be passed to the inject function
// that's being used.
let flagsParam: o.LiteralExpr|null =
(flags !== InjectFlags.Default || dep.optional) ? o.literal(flags) : null;
// Build up the arguments to the injectFn call.
const injectArgs = [dep.token];
if (flagsParam) {
injectArgs.push(flagsParam);
}
const injectFn = getInjectFn(target);
return o.importExpr(injectFn).callFn(injectArgs);
case R3ResolvedDependencyType.Attribute:
// In the case of attributes, the attribute name in question is given as the token.
return o.importExpr(R3.injectAttribute).callFn([dep.token]);
case R3ResolvedDependencyType.Invalid:
return o.importExpr(R3.invalidFactoryDep).callFn([o.literal(index)]);
default:
return unsupported(
`Unknown R3ResolvedDependencyType: ${R3ResolvedDependencyType[dep.resolved]}`);
// Build up the arguments to the injectFn call.
const injectArgs = [dep.token];
if (flagsParam) {
injectArgs.push(flagsParam);
}
const injectFn = getInjectFn(target);
return o.importExpr(injectFn).callFn(injectArgs);
} else {
// The `dep.attributeTypeName` value is defined, which indicates that this is an `@Attribute()`
// type dependency. For the generated JS we still want to use the `dep.token` value in case the
// name given for the attribute is not a string literal. For example given `@Attribute(foo())`,
// we want to generate `ɵɵinjectAttribute(foo())`.
//
// The `dep.attributeTypeName` is only actually used (in `createCtorDepType()`) to generate
// typings.
return o.importExpr(R3.injectAttribute).callFn([dep.token]);
}
}
@ -320,10 +285,8 @@ function createCtorDepsType(deps: R3DependencyMetadata[]): o.Type {
function createCtorDepType(dep: R3DependencyMetadata): o.LiteralMapExpr|null {
const entries: {key: string, quoted: boolean, value: o.Expression}[] = [];
if (dep.resolved === R3ResolvedDependencyType.Attribute) {
if (dep.attribute !== null) {
entries.push({key: 'attribute', value: dep.attribute, quoted: false});
}
if (dep.attributeNameType !== null) {
entries.push({key: 'attribute', value: dep.attributeNameType, quoted: false});
}
if (dep.optional) {
entries.push({key: 'optional', value: o.literal(true), quoted: false});

View File

@ -258,10 +258,6 @@ export class Identifiers {
};
static declareFactory: o.ExternalReference = {name: 'ɵɵngDeclareFactory', moduleName: CORE};
static R3FactoryTarget: o.ExternalReference = {name: 'ɵɵFactoryTarget', moduleName: CORE};
static R3ResolvedDependencyType:
o.ExternalReference = {name: 'ɵɵResolvedDependencyType', moduleName: CORE};
static R3FactoryDelegateType:
o.ExternalReference = {name: 'ɵɵFactoryDelegateType', moduleName: CORE};
static defineDirective: o.ExternalReference = {name: 'ɵɵdefineDirective', moduleName: CORE};
static declareDirective: o.ExternalReference = {name: 'ɵɵngDeclareDirective', moduleName: CORE};

View File

@ -7,7 +7,7 @@
*/
import * as core from '../../core/src/compiler/compiler_facade_interface';
import {R3FactoryTarget, R3ResolvedDependencyType} from '../public_api';
import {R3FactoryTarget} from '../public_api';
import * as compiler from '../src/compiler_facade_interface';
/**
@ -45,21 +45,6 @@ const compilerStringMap: compiler.StringMap = null! as core.StringMap;
const coreProvider: core.Provider = null! as compiler.Provider;
const compilerProvider: compiler.Provider = null! as core.Provider;
const coreR3ResolvedDependencyType: core.R3ResolvedDependencyType =
null! as compiler.R3ResolvedDependencyType;
const compilerR3ResolvedDependencyType: compiler.R3ResolvedDependencyType =
null! as core.R3ResolvedDependencyType;
const coreR3ResolvedDependencyType2: R3ResolvedDependencyType =
null! as core.R3ResolvedDependencyType;
const compilerR3ResolvedDependencyType2: R3ResolvedDependencyType =
null! as core.R3ResolvedDependencyType;
const coreR3ResolvedDependencyType3: core.R3ResolvedDependencyType =
null! as R3ResolvedDependencyType;
const compilerR3ResolvedDependencyType3: compiler.R3ResolvedDependencyType =
null! as R3ResolvedDependencyType;
const coreR3FactoryTarget: core.R3FactoryTarget = null! as compiler.R3FactoryTarget;
const compilerR3FactoryTarget: compiler.R3FactoryTarget = null! as core.R3FactoryTarget;

View File

@ -60,8 +60,7 @@ export interface CompilerFacade {
createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan;
R3ResolvedDependencyType: typeof R3ResolvedDependencyType;
R3FactoryTarget: typeof R3FactoryTarget;
R3FactoryTarget: typeof FactoryTarget;
ResourceLoader: {new(): ResourceLoader};
}
@ -83,13 +82,7 @@ export type StringMapWithRename = {
export type Provider = any;
export enum R3ResolvedDependencyType {
Token = 0,
Attribute = 1,
Invalid = 2,
}
export enum R3FactoryTarget {
export enum FactoryTarget {
Directive = 0,
Component = 1,
Injectable = 2,
@ -98,17 +91,17 @@ export enum R3FactoryTarget {
}
export interface R3DependencyMetadataFacade {
token: any;
resolved: R3ResolvedDependencyType;
token: unknown;
attribute: string|null;
host: boolean;
optional: boolean;
self: boolean;
skipSelf?: boolean;
skipSelf: boolean;
}
export interface R3DeclareDependencyMetadataFacade {
token: any;
resolved: R3ResolvedDependencyType;
token: unknown;
attribute?: boolean;
host?: boolean;
optional?: boolean;
self?: boolean;
@ -118,9 +111,7 @@ export interface R3DeclareDependencyMetadataFacade {
export interface R3PipeMetadataFacade {
name: string;
type: any;
typeArgumentCount: number;
pipeName: string;
deps: R3DependencyMetadataFacade[]|null;
pure: boolean;
}
@ -156,9 +147,7 @@ export interface R3InjectorMetadataFacade {
export interface R3DirectiveMetadataFacade {
name: string;
type: any;
typeArgumentCount: number;
typeSourceSpan: ParseSourceSpan;
deps: R3DependencyMetadataFacade[]|null;
selector: string|null;
queries: R3QueryMetadataFacade[];
host: {[key: string]: string};
@ -239,13 +228,13 @@ export interface R3FactoryDefMetadataFacade {
type: any;
typeArgumentCount: number;
deps: R3DependencyMetadataFacade[]|null;
target: R3FactoryTarget;
target: FactoryTarget;
}
export interface R3DeclareFactoryFacade {
type: Function;
deps: R3DeclareDependencyMetadataFacade[]|null;
target: R3FactoryTarget;
target: FactoryTarget;
}
export enum ViewEncapsulation {

View File

@ -268,9 +268,7 @@ export {
transitiveScopesFor as ɵtransitiveScopesFor,
} from './render3/jit/module';
export {
R3FactoryDelegateType as ɵɵFactoryDelegateType,
R3FactoryTarget as ɵɵFactoryTarget,
R3ResolvedDependencyType as ɵɵResolvedDependencyType,
ɵɵngDeclareComponent,
ɵɵngDeclareDirective,
ɵɵngDeclareFactory,

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CompilerFacade, getCompilerFacade, R3DependencyMetadataFacade, R3ResolvedDependencyType} from '../../compiler/compiler_facade';
import {R3DependencyMetadataFacade} from '../../compiler/compiler_facade';
import {Type} from '../../interface/type';
import {ReflectionCapabilities} from '../../reflection/reflection_capabilities';
import {Host, Inject, Optional, Self, SkipSelf} from '../metadata';
@ -23,25 +23,19 @@ export function reflectDependencies(type: Type<any>): R3DependencyMetadataFacade
}
export function convertDependencies(deps: any[]): R3DependencyMetadataFacade[] {
const compiler = getCompilerFacade();
return deps.map(dep => reflectDependency(compiler, dep));
return deps.map(dep => reflectDependency(dep));
}
function reflectDependency(compiler: CompilerFacade, dep: any|any[]): R3DependencyMetadataFacade {
function reflectDependency(dep: any|any[]): R3DependencyMetadataFacade {
const meta: R3DependencyMetadataFacade = {
token: null,
attribute: null,
host: false,
optional: false,
resolved: compiler.R3ResolvedDependencyType.Token,
self: false,
skipSelf: false,
};
function setTokenAndResolvedType(token: any): void {
meta.resolved = compiler.R3ResolvedDependencyType.Token;
meta.token = token;
}
if (Array.isArray(dep) && dep.length > 0) {
for (let j = 0; j < dep.length; j++) {
const param = dep[j];
@ -66,17 +60,15 @@ function reflectDependency(compiler: CompilerFacade, dep: any|any[]): R3Dependen
if (param.attributeName === undefined) {
throw new Error(`Attribute name must be defined.`);
}
meta.token = param.attributeName;
meta.resolved = compiler.R3ResolvedDependencyType.Attribute;
meta.attribute = param.attributeName;
} else {
setTokenAndResolvedType(param);
meta.token = param;
}
}
} else if (dep === undefined || (Array.isArray(dep) && dep.length === 0)) {
meta.token = undefined;
meta.resolved = R3ResolvedDependencyType.Invalid;
meta.token = null;
} else {
setTokenAndResolvedType(dep);
meta.token = dep;
}
return meta;
}

View File

@ -210,9 +210,13 @@ function addDirectiveFactoryDef(type: Type<any>, metadata: Directive|Component)
if (ngFactoryDef === null) {
const meta = getDirectiveMetadata(type, metadata);
const compiler = getCompilerFacade();
ngFactoryDef = compiler.compileFactory(
angularCoreEnv, `ng:///${type.name}/ɵfac.js`,
{...meta.metadata, target: compiler.R3FactoryTarget.Directive});
ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${type.name}/ɵfac.js`, {
name: meta.metadata.name,
type: meta.metadata.type,
typeArgumentCount: 0,
deps: reflectDependencies(type),
target: compiler.R3FactoryTarget.Directive
});
}
return ngFactoryDef;
},
@ -237,9 +241,7 @@ export function directiveMetadata(type: Type<any>, metadata: Directive): R3Direc
return {
name: type.name,
type: type,
typeArgumentCount: 0,
selector: metadata.selector !== undefined ? metadata.selector : null,
deps: reflectDependencies(type),
host: metadata.host || EMPTY_OBJ,
propMetadata: propMetadata,
inputs: metadata.inputs || EMPTY_ARRAY,

View File

@ -45,7 +45,7 @@ export function ɵɵngDeclareFactory(decl: R3DeclareFactoryFacade): unknown {
/**
* These enums are used in the partial factory declaration calls.
*/
export {R3FactoryTarget, R3ResolvedDependencyType, R3FactoryDelegateType} from '../../compiler/compiler_facade';
export {R3FactoryTarget} from '../../compiler/compiler_facade';
/**
* Compiles a partial injector declaration object into a full injector definition object.

View File

@ -23,9 +23,13 @@ export function compilePipe(type: Type<any>, meta: Pipe): void {
if (ngFactoryDef === null) {
const metadata = getPipeMetadata(type, meta);
const compiler = getCompilerFacade();
ngFactoryDef = compiler.compileFactory(
angularCoreEnv, `ng:///${metadata.name}/ɵfac.js`,
{...metadata, target: compiler.R3FactoryTarget.Pipe});
ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${metadata.name}/ɵfac.js`, {
name: metadata.name,
type: metadata.type,
typeArgumentCount: 0,
deps: reflectDependencies(type),
target: compiler.R3FactoryTarget.Pipe
});
}
return ngFactoryDef;
},
@ -50,9 +54,7 @@ export function compilePipe(type: Type<any>, meta: Pipe): void {
function getPipeMetadata(type: Type<any>, meta: Pipe): R3PipeMetadataFacade {
return {
type: type,
typeArgumentCount: 0,
name: type.name,
deps: reflectDependencies(type),
pipeName: meta.name,
pure: meta.pure !== undefined ? meta.pure : true
};

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, ɵcreateInjector, ɵɵFactoryTarget, ɵɵngDeclareFactory, ɵɵResolvedDependencyType} from '@angular/core';
import {Injector, ɵcreateInjector, ɵɵFactoryTarget, ɵɵngDeclareFactory} from '@angular/core';
import {ɵɵdefineInjector} from '@angular/core/src/di';
import {setCurrentInjector} from '@angular/core/src/di/injector_compatibility';
@ -47,7 +47,7 @@ class DependingClass {
constructor(readonly testClass: TestClass) {}
static ɵfac = ɵɵngDeclareFactory({
type: DependingClass,
deps: [{token: TestClass, resolved: ɵɵResolvedDependencyType.Token}],
deps: [{token: TestClass}],
target: ɵɵFactoryTarget.Injectable,
});
}

View File

@ -34,8 +34,6 @@ const PARTIAL_ONLY = new Set<string>([
'ɵɵngDeclareNgModule',
'ɵɵngDeclarePipe',
'ɵɵFactoryTarget',
'ɵɵResolvedDependencyType',
'ɵɵFactoryDelegateType',
'ChangeDetectionStrategy',
'ViewEncapsulation',
]);