feat(ivy): support providers and viewProviders (#25803)

PR Close #25803
This commit is contained in:
Marc Laval 2018-10-18 09:23:18 +02:00 committed by Matias Niemelä
parent 9dc52d9d04
commit b0476f308b
76 changed files with 4098 additions and 1645 deletions

View File

@ -128,7 +128,7 @@ describe('Renderer', () => {
})); }));
expect(addDefinitionsSpy.calls.first().args[2]) expect(addDefinitionsSpy.calls.first().args[2])
.toEqual( .toEqual(
`A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""]], factory: function A_Factory(t) { return new (t || A)(); }, features: [ɵngcc0.ɵPublicFeature] });`); `A.ngDirectiveDef = ɵngcc0.ɵdefineDirective({ type: A, selectors: [["", "a", ""]], factory: function A_Factory(t) { return new (t || A)(); } });`);
}); });
it('should call removeDecorators with the source code, a map of class decorators that have been analyzed', it('should call removeDecorators with the source code, a map of class decorators that have been analyzed',

View File

@ -118,6 +118,10 @@ export class ComponentDecoratorHandler implements
preserveWhitespaces = value; preserveWhitespaces = value;
} }
const viewProviders: Expression|null = component.has('viewProviders') ?
new WrappedNodeExpr(component.get('viewProviders') !) :
null;
// Go through the root directories for this project, and select the one with the smallest // Go through the root directories for this project, and select the one with the smallest
// relative path representation. // relative path representation.
const filePath = node.getSourceFile().fileName; const filePath = node.getSourceFile().fileName;
@ -202,6 +206,7 @@ export class ComponentDecoratorHandler implements
directives: EMPTY_MAP, directives: EMPTY_MAP,
wrapDirectivesInClosure: false, // wrapDirectivesInClosure: false, //
animations, animations,
viewProviders
}, },
parsedTemplate: template.nodes, parsedTemplate: template.nodes,
}, },

View File

@ -146,6 +146,9 @@ export function extractDirectiveMetadata(
const host = extractHostBindings(directive, decoratedElements, reflector, checker, coreModule); const host = extractHostBindings(directive, decoratedElements, reflector, checker, coreModule);
const providers: Expression|null =
directive.has('providers') ? new WrappedNodeExpr(directive.get('providers') !) : null;
// Determine if `ngOnChanges` is a lifecycle hook defined on the component. // Determine if `ngOnChanges` is a lifecycle hook defined on the component.
const usesOnChanges = members.some( const usesOnChanges = members.some(
member => !member.isStatic && member.kind === ClassMemberKind.Method && member => !member.isStatic && member.kind === ClassMemberKind.Method &&
@ -176,7 +179,7 @@ export function extractDirectiveMetadata(
outputs: {...outputsFromMeta, ...outputsFromFields}, queries, selector, outputs: {...outputsFromMeta, ...outputsFromFields}, queries, selector,
type: new WrappedNodeExpr(clazz.name !), type: new WrappedNodeExpr(clazz.name !),
typeArgumentCount: reflector.getGenericArityOfClass(clazz) || 0, typeArgumentCount: reflector.getGenericArityOfClass(clazz) || 0,
typeSourceSpan: null !, usesInheritance, exportAs, typeSourceSpan: null !, usesInheritance, exportAs, providers
}; };
return {decoratedElements, decorator: directive, metadata}; return {decoratedElements, decorator: directive, metadata};
} }

View File

@ -415,7 +415,6 @@ describe('compiler compliance', () => {
factory: function MyComponent_Factory(t){ factory: function MyComponent_Factory(t){
return new (t || MyComponent)(); return new (t || MyComponent)();
}, },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyComponent_Template(rf,ctx){ template: function MyComponent_Template(rf,ctx){
@ -470,7 +469,6 @@ describe('compiler compliance', () => {
type: ChildComponent, type: ChildComponent,
selectors: [["child"]], selectors: [["child"]],
factory: function ChildComponent_Factory(t) { return new (t || ChildComponent)(); }, factory: function ChildComponent_Factory(t) { return new (t || ChildComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function ChildComponent_Template(rf, ctx) { template: function ChildComponent_Template(rf, ctx) {
@ -485,8 +483,7 @@ describe('compiler compliance', () => {
SomeDirective.ngDirectiveDef = $r3$.ɵdefineDirective({ SomeDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: SomeDirective, type: SomeDirective,
selectors: [["", "some-directive", ""]], selectors: [["", "some-directive", ""]],
factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); }, factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); }
features: [$r3$.ɵPublicFeature]
}); });
`; `;
@ -498,7 +495,6 @@ describe('compiler compliance', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -543,8 +539,7 @@ describe('compiler compliance', () => {
SomeDirective.ngDirectiveDef = $r3$.ɵdefineDirective({ SomeDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: SomeDirective, type: SomeDirective,
selectors: [["div", "some-directive", "", 8, "foo", 3, "title", "", 9, "baz"]], selectors: [["div", "some-directive", "", 8, "foo", 3, "title", "", 9, "baz"]],
factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); }, factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); }
features: [$r3$.ɵPublicFeature]
}); });
`; `;
@ -553,8 +548,7 @@ describe('compiler compliance', () => {
OtherDirective.ngDirectiveDef = $r3$.ɵdefineDirective({ OtherDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: OtherDirective, type: OtherDirective,
selectors: [["", 5, "span", "title", "", 9, "baz"]], selectors: [["", 5, "span", "title", "", 9, "baz"]],
factory: function OtherDirective_Factory(t) {return new (t || OtherDirective)(); }, factory: function OtherDirective_Factory(t) {return new (t || OtherDirective)(); }
features: [$r3$.ɵPublicFeature]
}); });
`; `;
@ -590,8 +584,7 @@ describe('compiler compliance', () => {
hostBindings: function HostBindingDir_HostBindings(dirIndex, elIndex) { hostBindings: function HostBindingDir_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵload(dirIndex).dirId)); $r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵload(dirIndex).dirId));
}, },
hostVars: 1, hostVars: 1
features: [$r3$.ɵPublicFeature]
}); });
`; `;
@ -635,7 +628,6 @@ describe('compiler compliance', () => {
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, $r3$.ɵload(dirIndex).id))); $r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, $r3$.ɵload(dirIndex).id)));
}, },
hostVars: 3, hostVars: 3,
features: [$r3$.ɵPublicFeature],
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function HostBindingComp_Template(rf, ctx) {} template: function HostBindingComp_Template(rf, ctx) {}
@ -679,7 +671,6 @@ describe('compiler compliance', () => {
$r3$.ɵdirectiveInject(ElementRef), $r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(ElementRef), $r3$.ɵdirectiveInject(ViewContainerRef),
$r3$.ɵdirectiveInject(ChangeDetectorRef)); $r3$.ɵdirectiveInject(ChangeDetectorRef));
}, },
features: [$r3$.ɵPublicFeature],
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) {} template: function MyComponent_Template(rf, ctx) {}
@ -720,8 +711,7 @@ describe('compiler compliance', () => {
IfDirective.ngDirectiveDef = $r3$.ɵdefineDirective({ IfDirective.ngDirectiveDef = $r3$.ɵdefineDirective({
type: IfDirective, type: IfDirective,
selectors: [["", "if", ""]], selectors: [["", "if", ""]],
factory: function IfDirective_Factory(t) { return new (t || IfDirective)($r3$.ɵdirectiveInject(TemplateRef)); }, factory: function IfDirective_Factory(t) { return new (t || IfDirective)($r3$.ɵdirectiveInject(TemplateRef)); }
features: [$r3$.ɵPublicFeature]
});`; });`;
const MyComponentDefinition = ` const MyComponentDefinition = `
const $c1$ = ["foo", ""]; const $c1$ = ["foo", ""];
@ -743,7 +733,6 @@ describe('compiler compliance', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 3, consts: 3,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -806,7 +795,6 @@ describe('compiler compliance', () => {
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 3, vars: 3,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -888,7 +876,6 @@ describe('compiler compliance', () => {
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 11, vars: 11,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -952,7 +939,6 @@ describe('compiler compliance', () => {
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 3, vars: 3,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -1020,7 +1006,6 @@ describe('compiler compliance', () => {
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 8, vars: 8,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -1079,7 +1064,6 @@ describe('compiler compliance', () => {
type: SimpleComponent, type: SimpleComponent,
selectors: [["simple"]], selectors: [["simple"]],
factory: function SimpleComponent_Factory(t) { return new (t || SimpleComponent)(); }, factory: function SimpleComponent_Factory(t) { return new (t || SimpleComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function SimpleComponent_Template(rf, ctx) { template: function SimpleComponent_Template(rf, ctx) {
@ -1102,7 +1086,6 @@ describe('compiler compliance', () => {
type: ComplexComponent, type: ComplexComponent,
selectors: [["complex"]], selectors: [["complex"]],
factory: function ComplexComponent_Factory(t) { return new (t || ComplexComponent)(); }, factory: function ComplexComponent_Factory(t) { return new (t || ComplexComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 4, consts: 4,
vars: 0, vars: 0,
template: function ComplexComponent_Template(rf, ctx) { template: function ComplexComponent_Template(rf, ctx) {
@ -1171,7 +1154,6 @@ describe('compiler compliance', () => {
type: ViewQueryComponent, type: ViewQueryComponent,
selectors: [["view-query-component"]], selectors: [["view-query-component"]],
factory: function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); }, factory: function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); },
features: [$r3$.ɵPublicFeature],
viewQuery: function ViewQueryComponent_Query(rf, ctx) { viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵquery(0, SomeDirective, true); $r3$.ɵquery(0, SomeDirective, true);
@ -1348,9 +1330,9 @@ describe('compiler compliance', () => {
factory: function ContentQueryComponent_Factory(t) { factory: function ContentQueryComponent_Factory(t) {
return new (t || ContentQueryComponent)(); return new (t || ContentQueryComponent)();
}, },
contentQueries: function ContentQueryComponent_ContentQueries() { contentQueries: function ContentQueryComponent_ContentQueries(dirIndex) {
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, true)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, true), dirIndex);
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false), dirIndex);
}, },
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) { contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) {
const instance = $r3$.ɵload(dirIndex); const instance = $r3$.ɵload(dirIndex);
@ -1358,7 +1340,6 @@ describe('compiler compliance', () => {
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList(queryStartIndex))) && ($instance$.someDir = $tmp$.first)); ($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList(queryStartIndex))) && ($instance$.someDir = $tmp$.first));
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList((queryStartIndex + 1)))) && ($instance$.someDirList = $tmp$)); ($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList((queryStartIndex + 1)))) && ($instance$.someDirList = $tmp$));
}, },
features: [$r3$.ɵPublicFeature],
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function ContentQueryComponent_Template(rf, ctx) { template: function ContentQueryComponent_Template(rf, ctx) {
@ -1406,9 +1387,9 @@ describe('compiler compliance', () => {
ContentQueryComponent.ngComponentDef = $r3$.ɵdefineComponent({ ContentQueryComponent.ngComponentDef = $r3$.ɵdefineComponent({
contentQueries: function ContentQueryComponent_ContentQueries() { contentQueries: function ContentQueryComponent_ContentQueries(dirIndex) {
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e0_attrs$, true)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e0_attrs$, true), dirIndex);
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e1_attrs$, false)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e1_attrs$, false), dirIndex);
}, },
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) { contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) {
const instance = $r3$.ɵload(dirIndex); const instance = $r3$.ɵload(dirIndex);
@ -1459,11 +1440,11 @@ describe('compiler compliance', () => {
ContentQueryComponent.ngComponentDef = $r3$.ɵdefineComponent({ ContentQueryComponent.ngComponentDef = $r3$.ɵdefineComponent({
contentQueries: function ContentQueryComponent_ContentQueries() { contentQueries: function ContentQueryComponent_ContentQueries(dirIndex) {
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e0_attrs$ , true, TemplateRef)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e0_attrs$ , true, TemplateRef), dirIndex);
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, true, ElementRef)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, true, ElementRef), dirIndex);
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e1_attrs$, false, ElementRef)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, $e1_attrs$, false, ElementRef), dirIndex);
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false, TemplateRef)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false, TemplateRef), dirIndex);
}, },
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) { contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) {
const instance = $r3$.ɵload(dirIndex); const instance = $r3$.ɵload(dirIndex);
@ -1552,7 +1533,6 @@ describe('compiler compliance', () => {
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
features: [$r3$.ɵPublicFeature],
consts: 6, consts: 6,
vars: 17, vars: 17,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -1616,7 +1596,6 @@ describe('compiler compliance', () => {
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
features: [$r3$.ɵPublicFeature],
consts: 6, consts: 6,
vars: 27, vars: 27,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -1671,7 +1650,6 @@ describe('compiler compliance', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 3, consts: 3,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -1765,7 +1743,6 @@ describe('compiler compliance', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 6, consts: 6,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -1911,7 +1888,7 @@ describe('compiler compliance', () => {
selectors: [["lifecycle-comp"]], selectors: [["lifecycle-comp"]],
factory: function LifecycleComp_Factory(t) { return new (t || LifecycleComp)(); }, factory: function LifecycleComp_Factory(t) { return new (t || LifecycleComp)(); },
inputs: {nameMin: "name"}, inputs: {nameMin: "name"},
features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature], features: [$r3$.ɵNgOnChangesFeature],
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function LifecycleComp_Template(rf, ctx) {} template: function LifecycleComp_Template(rf, ctx) {}
@ -1922,7 +1899,6 @@ describe('compiler compliance', () => {
type: SimpleLayout, type: SimpleLayout,
selectors: [["simple-layout"]], selectors: [["simple-layout"]],
factory: function SimpleLayout_Factory(t) { return new (t || SimpleLayout)(); }, factory: function SimpleLayout_Factory(t) { return new (t || SimpleLayout)(); },
features: [$r3$.ɵPublicFeature],
consts: 2, consts: 2,
vars: 2, vars: 2,
template: function SimpleLayout_Template(rf, ctx) { template: function SimpleLayout_Template(rf, ctx) {
@ -2032,7 +2008,7 @@ describe('compiler compliance', () => {
factory: function ForOfDirective_Factory(t) { factory: function ForOfDirective_Factory(t) {
return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef)); return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
}, },
features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature], features: [$r3$.ɵNgOnChangesFeature],
inputs: {forOf: "forOf"} inputs: {forOf: "forOf"}
}); });
`; `;
@ -2052,7 +2028,6 @@ describe('compiler compliance', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx){ template: function MyComponent_Template(rf, ctx){
@ -2108,7 +2083,7 @@ describe('compiler compliance', () => {
factory: function ForOfDirective_Factory(t) { factory: function ForOfDirective_Factory(t) {
return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef)); return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
}, },
features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature], features: [$r3$.ɵNgOnChangesFeature],
inputs: {forOf: "forOf"} inputs: {forOf: "forOf"}
}); });
`; `;
@ -2131,7 +2106,6 @@ describe('compiler compliance', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -2231,7 +2205,6 @@ describe('compiler compliance', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {

View File

@ -42,7 +42,6 @@ describe('compiler compliance: directives', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -88,7 +87,6 @@ describe('compiler compliance: directives', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {

View File

@ -202,7 +202,6 @@ describe('compiler compliance: listen()', () => {
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
features: [$r3$.ɵPublicFeature],
consts: 4, consts: 4,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {

View File

@ -0,0 +1,152 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* 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 {setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
describe('compiler compliance: providers', () => {
const angularFiles = setup({
compileAngular: false,
compileFakeCore: true,
compileAnimations: false,
});
it('should emit the ProvidersFeature feature when providers and viewProviders', () => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule} from '@angular/core';
abstract class Greeter { abstract greet(): string; }
class GreeterEN implements Greeter {
greet() { return 'Hi'; }
}
@Component({
selector: 'my-component',
template: '<div></div>',
providers: [GreeterEN, {provide: Greeter, useClass: GreeterEN}],
viewProviders: [GreeterEN]
})
export class MyComponent {
}
@NgModule({declarations: [MyComponent]})
export class MyModule {}
`
}
};
const result = compile(files, angularFiles);
expectEmit(
result.source,
'features: [i0.ɵProvidersFeature([GreeterEN, {provide: Greeter, useClass: GreeterEN}], [GreeterEN])],',
'Incorrect features');
});
it('should emit the ProvidersFeature feature when providers only', () => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule} from '@angular/core';
abstract class Greeter { abstract greet(): string; }
class GreeterEN implements Greeter {
greet() { return 'Hi'; }
}
@Component({
selector: 'my-component',
template: '<div></div>',
providers: [GreeterEN, {provide: Greeter, useClass: GreeterEN}]
})
export class MyComponent {
}
@NgModule({declarations: [MyComponent]})
export class MyModule {}
`
}
};
const result = compile(files, angularFiles);
expectEmit(
result.source,
'features: [i0.ɵProvidersFeature([GreeterEN, {provide: Greeter, useClass: GreeterEN}])],',
'Incorrect features');
});
it('should emit the ProvidersFeature feature when viewProviders only', () => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule} from '@angular/core';
abstract class Greeter { abstract greet(): string; }
class GreeterEN implements Greeter {
greet() { return 'Hi'; }
}
@Component({
selector: 'my-component',
template: '<div></div>',
viewProviders: [GreeterEN]
})
export class MyComponent {
}
@NgModule({declarations: [MyComponent]})
export class MyModule {}
`
}
};
const result = compile(files, angularFiles);
expectEmit(
result.source, 'features: [i0.ɵProvidersFeature([], [GreeterEN])],', 'Incorrect features');
});
it('should not emit the ProvidersFeature feature when no providers', () => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule} from '@angular/core';
abstract class Greeter { abstract greet(): string; }
class GreeterEN implements Greeter {
greet() { return 'Hi'; }
}
@Component({
selector: 'my-component',
template: '<div></div>'
})
export class MyComponent {
}
@NgModule({declarations: [MyComponent]})
export class MyModule {}
`
}
};
const result = compile(files, angularFiles);
expectEmit(
result.source, `
export class MyComponent {
}
MyComponent.ngComponentDef = i0.ɵdefineComponent({ type: MyComponent, selectors: [["my-component"]], factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, consts: 1, vars: 0, template: function MyComponent_Template(rf, ctx) { if (rf & 1) {
i0.ɵelement(0, "div");
} } });`,
'Incorrect features');
});
});

View File

@ -128,7 +128,6 @@ describe('compiler compliance: styling', () => {
factory:function MyComponent_Factory(t){ factory:function MyComponent_Factory(t){
return new (t || MyComponent)(); return new (t || MyComponent)();
}, },
features: [$r3$.ɵPublicFeature],
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {
@ -170,7 +169,6 @@ describe('compiler compliance: styling', () => {
factory:function MyComponent_Factory(t){ factory:function MyComponent_Factory(t){
return new (t || MyComponent)(); return new (t || MyComponent)();
}, },
features: [$r3$.ɵPublicFeature],
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {
@ -308,7 +306,6 @@ describe('compiler compliance: styling', () => {
factory:function MyComponent_Factory(t){ factory:function MyComponent_Factory(t){
return new (t || MyComponent)(); return new (t || MyComponent)();
}, },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {
@ -367,7 +364,6 @@ describe('compiler compliance: styling', () => {
factory: function MyComponent_Factory(t) { factory: function MyComponent_Factory(t) {
return new (t || MyComponent)(); return new (t || MyComponent)();
}, },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -506,7 +502,6 @@ describe('compiler compliance: styling', () => {
factory:function MyComponent_Factory(t){ factory:function MyComponent_Factory(t){
return new (t || MyComponent)(); return new (t || MyComponent)();
}, },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {
@ -563,7 +558,6 @@ describe('compiler compliance: styling', () => {
factory:function MyComponent_Factory(t){ factory:function MyComponent_Factory(t){
return new (t || MyComponent)(); return new (t || MyComponent)();
}, },
features: [$r3$.ɵPublicFeature],
consts: 1, consts: 1,
vars: 2, vars: 2,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {

View File

@ -175,7 +175,7 @@ export class Identifiers {
static InheritDefinitionFeature: static InheritDefinitionFeature:
o.ExternalReference = {name: 'ɵInheritDefinitionFeature', moduleName: CORE}; o.ExternalReference = {name: 'ɵInheritDefinitionFeature', moduleName: CORE};
static PublicFeature: o.ExternalReference = {name: 'ɵPublicFeature', moduleName: CORE}; static ProvidersFeature: o.ExternalReference = {name: 'ɵProvidersFeature', moduleName: CORE};
static listener: o.ExternalReference = {name: 'ɵlistener', moduleName: CORE}; static listener: o.ExternalReference = {name: 'ɵlistener', moduleName: CORE};

View File

@ -103,6 +103,11 @@ export interface R3DirectiveMetadata {
* if any. * if any.
*/ */
exportAs: string|null; exportAs: string|null;
/**
* The list of providers defined in the directive.
*/
providers: o.Expression|null;
} }
/** /**
@ -180,6 +185,11 @@ export interface R3ComponentMetadata extends R3DirectiveMetadata {
* A collection of animation triggers that will be used in the component template. * A collection of animation triggers that will be used in the component template.
*/ */
animations: o.Expression|null; animations: o.Expression|null;
/**
* The list of view providers defined in the component.
*/
viewProviders: o.Expression|null;
} }
/** /**

View File

@ -82,11 +82,30 @@ function baseDirectiveFields(
// e.g 'outputs: {a: 'a'}` // e.g 'outputs: {a: 'a'}`
definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs)); definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs));
if (meta.exportAs !== null) {
definitionMap.set('exportAs', o.literal(meta.exportAs));
}
return {definitionMap, statements: result.statements};
}
/**
* Add features to the definition map.
*/
function addFeatures(
definitionMap: DefinitionMap, meta: R3DirectiveMetadata | R3ComponentMetadata) {
// e.g. `features: [NgOnChangesFeature]` // e.g. `features: [NgOnChangesFeature]`
const features: o.Expression[] = []; const features: o.Expression[] = [];
// TODO: add `PublicFeature` so that directives get registered to the DI - make this configurable const providers = meta.providers;
features.push(o.importExpr(R3.PublicFeature)); const viewProviders = (meta as R3ComponentMetadata).viewProviders;
if (providers || viewProviders) {
const args = [providers || new o.LiteralArrayExpr([])];
if (viewProviders) {
args.push(viewProviders);
}
features.push(o.importExpr(R3.ProvidersFeature).callFn(args));
}
if (meta.usesInheritance) { if (meta.usesInheritance) {
features.push(o.importExpr(R3.InheritDefinitionFeature)); features.push(o.importExpr(R3.InheritDefinitionFeature));
@ -97,11 +116,6 @@ function baseDirectiveFields(
if (features.length) { if (features.length) {
definitionMap.set('features', o.literalArr(features)); definitionMap.set('features', o.literalArr(features));
} }
if (meta.exportAs !== null) {
definitionMap.set('exportAs', o.literal(meta.exportAs));
}
return {definitionMap, statements: result.statements};
} }
/** /**
@ -111,6 +125,7 @@ export function compileDirectiveFromMetadata(
meta: R3DirectiveMetadata, constantPool: ConstantPool, meta: R3DirectiveMetadata, constantPool: ConstantPool,
bindingParser: BindingParser): R3DirectiveDef { bindingParser: BindingParser): R3DirectiveDef {
const {definitionMap, statements} = baseDirectiveFields(meta, constantPool, bindingParser); const {definitionMap, statements} = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta);
const expression = o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()]); const expression = o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()]);
// On the type side, remove newlines from the selector as it will need to fit into a TypeScript // On the type side, remove newlines from the selector as it will need to fit into a TypeScript
@ -164,6 +179,7 @@ export function compileComponentFromMetadata(
meta: R3ComponentMetadata, constantPool: ConstantPool, meta: R3ComponentMetadata, constantPool: ConstantPool,
bindingParser: BindingParser): R3ComponentDef { bindingParser: BindingParser): R3ComponentDef {
const {definitionMap, statements} = baseDirectiveFields(meta, constantPool, bindingParser); const {definitionMap, statements} = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta);
const selector = meta.selector && CssSelector.parse(meta.selector); const selector = meta.selector && CssSelector.parse(meta.selector);
const firstSelector = selector && selector[0]; const firstSelector = selector && selector[0];
@ -320,6 +336,8 @@ export function compileComponentFromRender2(
encapsulation: encapsulation:
(summary.template && summary.template.encapsulation) || core.ViewEncapsulation.Emulated, (summary.template && summary.template.encapsulation) || core.ViewEncapsulation.Emulated,
animations: null, animations: null,
viewProviders:
component.viewProviders.length > 0 ? new o.WrappedNodeExpr(component.viewProviders) : null
}; };
const res = compileComponentFromMetadata(meta, outputCtx.constantPool, bindingParser); const res = compileComponentFromMetadata(meta, outputCtx.constantPool, bindingParser);
@ -362,6 +380,7 @@ function directiveMetadataFromGlobalMetadata(
outputs: directive.outputs, outputs: directive.outputs,
usesInheritance: false, usesInheritance: false,
exportAs: null, exportAs: null,
providers: directive.providers.length > 0 ? new o.WrappedNodeExpr(directive.providers) : null
}; };
} }
@ -451,11 +470,15 @@ function createContentQueriesFunction(
if (meta.queries.length) { if (meta.queries.length) {
const statements: o.Statement[] = meta.queries.map((query: R3QueryMetadata) => { const statements: o.Statement[] = meta.queries.map((query: R3QueryMetadata) => {
const queryDefinition = createQueryDefinition(query, constantPool, null); const queryDefinition = createQueryDefinition(query, constantPool, null);
return o.importExpr(R3.registerContentQuery).callFn([queryDefinition]).toStmt(); return o.importExpr(R3.registerContentQuery)
.callFn([queryDefinition, o.variable('dirIndex')])
.toStmt();
}); });
const typeName = meta.name; const typeName = meta.name;
const parameters = [new o.FnParam('dirIndex', o.NUMBER_TYPE)];
return o.fn( return o.fn(
[], statements, o.INFERRED_TYPE, null, typeName ? `${typeName}_ContentQueries` : null); parameters, statements, o.INFERRED_TYPE, null,
typeName ? `${typeName}_ContentQueries` : null);
} }
return null; return null;

View File

@ -25,7 +25,7 @@ export {
getFactoryOf as ɵgetFactoryOf, getFactoryOf as ɵgetFactoryOf,
getInheritedFactory as ɵgetInheritedFactory, getInheritedFactory as ɵgetInheritedFactory,
templateRefExtractor as ɵtemplateRefExtractor, templateRefExtractor as ɵtemplateRefExtractor,
PublicFeature as ɵPublicFeature, ProvidersFeature as ɵProvidersResolver,
InheritDefinitionFeature as ɵInheritDefinitionFeature, InheritDefinitionFeature as ɵInheritDefinitionFeature,
NgOnChangesFeature as ɵNgOnChangesFeature, NgOnChangesFeature as ɵNgOnChangesFeature,
NgModuleType as ɵNgModuleType, NgModuleType as ɵNgModuleType,

View File

@ -8,6 +8,7 @@
import {Type} from '../type'; import {Type} from '../type';
import {stringify} from '../util'; import {stringify} from '../util';
import {getClosureSafeProperty} from '../util/property';
@ -22,6 +23,8 @@ import {stringify} from '../util';
*/ */
export interface ForwardRefFn { (): any; } export interface ForwardRefFn { (): any; }
const __forward_ref__ = getClosureSafeProperty({__forward_ref__: getClosureSafeProperty});
/** /**
* Allows to refer to references which are not yet defined. * Allows to refer to references which are not yet defined.
* *
@ -53,10 +56,11 @@ export function forwardRef(forwardRefFn: ForwardRefFn): Type<any> {
* @see `forwardRef` * @see `forwardRef`
* @publicApi * @publicApi
*/ */
export function resolveForwardRef(type: any): any { export function resolveForwardRef<T>(type: T): T {
if (typeof type === 'function' && type.hasOwnProperty('__forward_ref__') && const fn: any = type;
type.__forward_ref__ === forwardRef) { if (typeof fn === 'function' && fn.hasOwnProperty(__forward_ref__) &&
return (<ForwardRefFn>type)(); fn.__forward_ref__ === forwardRef) {
return fn();
} else { } else {
return type; return type;
} }

View File

@ -431,6 +431,17 @@ export function setCurrentInjector(injector: Injector | null | undefined): Injec
_currentInjector = injector; _currentInjector = injector;
return former; return former;
} }
/**
* Current implementation of inject.
*
* By default, it is `injectInjectorOnly`, which makes it `Injector`-only aware. It can be changed
* to `directiveInject`, which brings in the `NodeInjector` system of ivy. It is designed this
* way for two reasons:
* 1. `Injector` should not depend on ivy logic.
* 2. To maintain tree shake-ability we don't want to bring in unnecessary code.
*/
let _injectImplementation: (<T>(token: Type<T>| InjectionToken<T>, flags: InjectFlags) => T | null)|
undefined;
/** /**
* Injects a token from the currently active injector. * Injects a token from the currently active injector.
@ -452,21 +463,53 @@ export function setCurrentInjector(injector: Injector | null | undefined): Injec
export function inject<T>(token: Type<T>| InjectionToken<T>): T; export function inject<T>(token: Type<T>| InjectionToken<T>): T;
export function inject<T>(token: Type<T>| InjectionToken<T>, flags?: InjectFlags): T|null; export function inject<T>(token: Type<T>| InjectionToken<T>, flags?: InjectFlags): T|null;
export function inject<T>(token: Type<T>| InjectionToken<T>, flags = InjectFlags.Default): T|null { export function inject<T>(token: Type<T>| InjectionToken<T>, flags = InjectFlags.Default): T|null {
return (_injectImplementation || injectInjectorOnly)(token, flags);
}
/**
* Sets the current inject implementation.
*/
export function setInjectImplementation(
impl: (<T>(token: Type<T>| InjectionToken<T>, flags?: InjectFlags) => T | null) | undefined):
(<T>(token: Type<T>| InjectionToken<T>, flags?: InjectFlags) => T | null)|undefined {
const previous = _injectImplementation;
_injectImplementation = impl;
return previous;
}
export function injectInjectorOnly<T>(token: Type<T>| InjectionToken<T>): T;
export function injectInjectorOnly<T>(token: Type<T>| InjectionToken<T>, flags?: InjectFlags): T|
null;
export function injectInjectorOnly<T>(
token: Type<T>| InjectionToken<T>, flags = InjectFlags.Default): T|null {
if (_currentInjector === undefined) { if (_currentInjector === undefined) {
throw new Error(`inject() must be called from an injection context`); throw new Error(`inject() must be called from an injection context`);
} else if (_currentInjector === null) { } else if (_currentInjector === null) {
const injectableDef: InjectableDef<T>|null = getInjectableDef(token); return injectRootLimpMode(token, undefined, flags);
if (injectableDef && injectableDef.providedIn == 'root') {
return injectableDef.value === undefined ? injectableDef.value = injectableDef.factory() :
injectableDef.value;
}
if (flags & InjectFlags.Optional) return null;
throw new Error(`Injector: NOT_FOUND [${stringify(token)}]`);
} else { } else {
return _currentInjector.get(token, flags & InjectFlags.Optional ? null : undefined, flags); return _currentInjector.get(token, flags & InjectFlags.Optional ? null : undefined, flags);
} }
} }
/**
* Injects `root` tokens in limp mode.
*
* If no injector exists, we can still inject tree-shakable providers which have `providedIn` set to
* `"root"`. This is known as the limp mode injection. In such case the value is stored in the
* `InjectableDef`.
*/
export function injectRootLimpMode<T>(
token: Type<T>| InjectionToken<T>, notFoundValue: T | undefined, flags: InjectFlags): T|null {
const injectableDef: InjectableDef<T>|null = getInjectableDef(token);
if (injectableDef && injectableDef.providedIn == 'root') {
return injectableDef.value === undefined ? injectableDef.value = injectableDef.factory() :
injectableDef.value;
}
if (flags & InjectFlags.Optional) return null;
if (notFoundValue !== undefined) return notFoundValue;
throw new Error(`Injector: NOT_FOUND [${stringify(token)}]`);
}
export function injectArgs(types: (Type<any>| InjectionToken<any>| any[])[]): any[] { export function injectArgs(types: (Type<any>| InjectionToken<any>| any[])[]): any[] {
const args: any[] = []; const args: any[] = [];
for (let i = 0; i < types.length; i++) { for (let i = 0; i < types.length; i++) {

View File

@ -165,7 +165,7 @@ export class R3Injector {
if (def && this.injectableDefInScope(def)) { if (def && this.injectableDefInScope(def)) {
// Found an ngInjectableDef and it's scoped to this injector. Pretend as if it was here // Found an ngInjectableDef and it's scoped to this injector. Pretend as if it was here
// all along. // all along.
record = injectableDefRecord(token); record = makeRecord(injectableDefFactory(token), NOT_YET);
this.records.set(token, record); this.records.set(token, record);
} }
} }
@ -328,7 +328,7 @@ export class R3Injector {
} }
} }
function injectableDefRecord(token: Type<any>| InjectionToken<any>): Record<any> { function injectableDefFactory(token: Type<any>| InjectionToken<any>): () => any {
const injectableDef = getInjectableDef(token as InjectableType<any>); const injectableDef = getInjectableDef(token as InjectableType<any>);
if (injectableDef === null) { if (injectableDef === null) {
if (token instanceof InjectionToken) { if (token instanceof InjectionToken) {
@ -336,21 +336,34 @@ function injectableDefRecord(token: Type<any>| InjectionToken<any>): Record<any>
} }
// TODO(alxhub): there should probably be a strict mode which throws here instead of assuming a // TODO(alxhub): there should probably be a strict mode which throws here instead of assuming a
// no-args constructor. // no-args constructor.
return makeRecord(() => new (token as Type<any>)()); return () => new (token as Type<any>)();
} }
return makeRecord(injectableDef.factory); return injectableDef.factory;
} }
function providerToRecord(provider: SingleProvider): Record<any> { function providerToRecord(provider: SingleProvider): Record<any> {
let factory: (() => any)|undefined = providerToFactory(provider);
if (isValueProvider(provider)) {
return makeRecord(undefined, provider.useValue);
} else {
return makeRecord(factory, NOT_YET);
}
}
/**
* Converts a `SingleProvider` into a factory function.
*
* @param provider provider to convert to factory
*/
export function providerToFactory(provider: SingleProvider): () => any {
let token = resolveForwardRef(provider); let token = resolveForwardRef(provider);
let value: any = NOT_YET;
let factory: (() => any)|undefined = undefined; let factory: (() => any)|undefined = undefined;
if (isTypeProvider(provider)) { if (isTypeProvider(provider)) {
return injectableDefRecord(provider); return injectableDefFactory(provider);
} else { } else {
token = resolveForwardRef(provider.provide); token = resolveForwardRef(provider.provide);
if (isValueProvider(provider)) { if (isValueProvider(provider)) {
value = provider.useValue; factory = () => provider.useValue;
} else if (isExistingProvider(provider)) { } else if (isExistingProvider(provider)) {
factory = () => inject(provider.useExisting); factory = () => inject(provider.useExisting);
} else if (isFactoryProvider(provider)) { } else if (isFactoryProvider(provider)) {
@ -360,11 +373,11 @@ function providerToRecord(provider: SingleProvider): Record<any> {
if (hasDeps(provider)) { if (hasDeps(provider)) {
factory = () => new (classRef)(...injectArgs(provider.deps)); factory = () => new (classRef)(...injectArgs(provider.deps));
} else { } else {
return injectableDefRecord(classRef); return injectableDefFactory(classRef);
} }
} }
} }
return makeRecord(factory, value); return factory;
} }
function makeRecord<T>( function makeRecord<T>(
@ -392,7 +405,7 @@ function isFactoryProvider(value: SingleProvider): value is FactoryProvider {
return !!(value as FactoryProvider).useFactory; return !!(value as FactoryProvider).useFactory;
} }
function isTypeProvider(value: SingleProvider): value is TypeProvider { export function isTypeProvider(value: SingleProvider): value is TypeProvider {
return typeof value === 'function'; return typeof value === 'function';
} }

View File

@ -15,14 +15,16 @@ import {Sanitizer} from '../sanitization/security';
import {assertComponentType, assertDefined} from './assert'; import {assertComponentType, assertDefined} from './assert';
import {getComponentViewByInstance} from './context_discovery'; import {getComponentViewByInstance} from './context_discovery';
import {getComponentDef} from './definition'; import {getComponentDef} from './definition';
import {diPublicInInjector, getOrCreateNodeInjectorForNode} from './di';
import {queueInitHooks, queueLifecycleHooks} from './hooks'; import {queueInitHooks, queueLifecycleHooks} from './hooks';
import {CLEAN_PROMISE, baseDirectiveCreate, createLViewData, createNodeAtIndex, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, getOrCreateTView, leaveView, locateHostElement, prefillHostVars, resetComponentState, setHostBindings} from './instructions'; import {CLEAN_PROMISE, createLViewData, createNodeAtIndex, createTView, detectChangesInternal, executeInitAndContentHooks, getOrCreateTView, initNodeFlags, instantiateRootComponent, locateHostElement, prefillHostVars, setHostBindings} from './instructions';
import {ComponentDef, ComponentType} from './interfaces/definition'; import {ComponentDef, ComponentType} from './interfaces/definition';
import {TElementNode, TNodeFlags, TNodeType} from './interfaces/node'; import {TElementNode, TNodeFlags, TNodeType} from './interfaces/node';
import {PlayerHandler} from './interfaces/player'; import {PlayerHandler} from './interfaces/player';
import {RElement, RNode, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer'; import {RElement, RNode, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {CONTEXT, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LViewData, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view'; import {CONTEXT, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LViewData, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
import {publishDefaultGlobalUtils} from './publish_global_util'; import {publishDefaultGlobalUtils} from './publish_global_util';
import {enterView, leaveView, resetComponentState} from './state';
import {getRootView, readElementValue, readPatchedLViewData, stringify} from './util'; import {getRootView, readElementValue, readPatchedLViewData, stringify} from './util';
@ -130,13 +132,12 @@ export function renderComponent<T>(
let component: T; let component: T;
try { try {
if (rendererFactory.begin) rendererFactory.begin(); if (rendererFactory.begin) rendererFactory.begin();
const componentView = const componentView =
createRootComponentView(hostRNode, componentDef, rootView, renderer, sanitizer); createRootComponentView(hostRNode, componentDef, rootView, renderer, sanitizer);
component = createRootComponent( component = createRootComponent(
hostRNode, componentView, componentDef, rootView, rootContext, opts.hostFeatures || null); hostRNode, componentView, componentDef, rootView, rootContext, opts.hostFeatures || null);
executeInitAndContentHooks(); executeInitAndContentHooks(rootView);
detectChangesInternal(componentView, component); detectChangesInternal(componentView, component);
} finally { } finally {
leaveView(oldView); leaveView(oldView);
@ -171,9 +172,9 @@ export function createRootComponentView(
if (tView.firstTemplatePass) { if (tView.firstTemplatePass) {
tView.expandoInstructions = ROOT_EXPANDO_INSTRUCTIONS.slice(); tView.expandoInstructions = ROOT_EXPANDO_INSTRUCTIONS.slice();
if (def.diPublic) def.diPublic(def); diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), rootView, def.type);
tNode.flags = tNode.flags = TNodeFlags.isComponent;
rootView.length << TNodeFlags.DirectiveStartingIndexShift | TNodeFlags.isComponent; initNodeFlags(tNode, rootView.length, 1);
} }
// Store component view at node index, with node as the HOST // Store component view at node index, with node as the HOST
@ -189,16 +190,17 @@ export function createRootComponentView(
export function createRootComponent<T>( export function createRootComponent<T>(
hostRNode: RNode | null, componentView: LViewData, componentDef: ComponentDef<T>, hostRNode: RNode | null, componentView: LViewData, componentDef: ComponentDef<T>,
rootView: LViewData, rootContext: RootContext, hostFeatures: HostFeature[] | null): any { rootView: LViewData, rootContext: RootContext, hostFeatures: HostFeature[] | null): any {
const tView = rootView[TVIEW];
// Create directive instance with factory() and store at next index in viewData // Create directive instance with factory() and store at next index in viewData
const component = const component = instantiateRootComponent(tView, rootView, componentDef);
baseDirectiveCreate(rootView.length, componentDef.factory() as T, componentDef, hostRNode);
rootContext.components.push(component); rootContext.components.push(component);
componentView[CONTEXT] = component; componentView[CONTEXT] = component;
hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef)); hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef));
if (rootView[TVIEW].firstTemplatePass) prefillHostVars(componentDef.hostVars);
setHostBindings(); if (tView.firstTemplatePass) prefillHostVars(tView, rootView, componentDef.hostVars);
setHostBindings(tView, rootView);
return component; return component;
} }

View File

@ -19,11 +19,12 @@ import {Type} from '../type';
import {assertComponentType, assertDefined} from './assert'; import {assertComponentType, assertDefined} from './assert';
import {LifecycleHooksFeature, createRootComponent, createRootComponentView, createRootContext} from './component'; import {LifecycleHooksFeature, createRootComponent, createRootComponentView, createRootContext} from './component';
import {getComponentDef} from './definition'; import {getComponentDef} from './definition';
import {adjustBlueprintForNewNode, createLViewData, createNodeAtIndex, createTView, createViewNode, elementCreate, enterView, locateHostElement, renderEmbeddedTemplate} from './instructions'; import {createLViewData, createNodeAtIndex, createTView, createViewNode, elementCreate, locateHostElement, renderEmbeddedTemplate} from './instructions';
import {ComponentDef, RenderFlags} from './interfaces/definition'; import {ComponentDef, RenderFlags} from './interfaces/definition';
import {TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node'; import {TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node';
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer'; import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {FLAGS, INJECTOR, LViewData, LViewFlags, RootContext, TVIEW} from './interfaces/view'; import {FLAGS, HEADER_OFFSET, INJECTOR, LViewData, LViewFlags, RootContext, TVIEW} from './interfaces/view';
import {enterView} from './state';
import {getTNode} from './util'; import {getTNode} from './util';
import {createElementRef} from './view_engine_compatibility'; import {createElementRef} from './view_engine_compatibility';
import {RootViewRef, ViewRef} from './view_ref'; import {RootViewRef, ViewRef} from './view_ref';
@ -114,9 +115,6 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
elementCreate(this.selector, rendererFactory.createRenderer(null, this.componentDef)) : elementCreate(this.selector, rendererFactory.createRenderer(null, this.componentDef)) :
locateHostElement(rendererFactory, rootSelectorOrNode); locateHostElement(rendererFactory, rootSelectorOrNode);
// The first index of the first selector is the tag name.
const componentTag = this.componentDef.selectors ![0] ![0] as string;
const rootFlags = this.componentDef.onPush ? LViewFlags.Dirty | LViewFlags.IsRoot : const rootFlags = this.componentDef.onPush ? LViewFlags.Dirty | LViewFlags.IsRoot :
LViewFlags.CheckAlways | LViewFlags.IsRoot; LViewFlags.CheckAlways | LViewFlags.IsRoot;
const rootContext: RootContext = ngModule && !isInternalRootView ? const rootContext: RootContext = ngModule && !isInternalRootView ?
@ -145,15 +143,25 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
// projection instruction. This is needed to support the reprojection of these nodes. // projection instruction. This is needed to support the reprojection of these nodes.
if (projectableNodes) { if (projectableNodes) {
let index = 0; let index = 0;
const tView = rootView[TVIEW];
const projection: TNode[] = tElementNode.projection = []; const projection: TNode[] = tElementNode.projection = [];
for (let i = 0; i < projectableNodes.length; i++) { for (let i = 0; i < projectableNodes.length; i++) {
const nodeList = projectableNodes[i]; const nodeList = projectableNodes[i];
let firstTNode: TNode|null = null; let firstTNode: TNode|null = null;
let previousTNode: TNode|null = null; let previousTNode: TNode|null = null;
for (let j = 0; j < nodeList.length; j++) { for (let j = 0; j < nodeList.length; j++) {
adjustBlueprintForNewNode(rootView); if (tView.firstTemplatePass) {
// For dynamically created components such as ComponentRef, we create a new TView for
// each insert. This is not ideal since we should be sharing the TViews.
// Also the logic here should be shared with `component.ts`'s `renderComponent`
// method.
tView.expandoStartIndex++;
tView.blueprint.splice(++index + HEADER_OFFSET, 0, null);
tView.data.splice(index + HEADER_OFFSET, 0, null);
rootView.splice(index + HEADER_OFFSET, 0, null);
}
const tNode = const tNode =
createNodeAtIndex(++index, TNodeType.Element, nodeList[j] as RElement, null, null); createNodeAtIndex(index, TNodeType.Element, nodeList[j] as RElement, null, null);
previousTNode ? (previousTNode.next = tNode) : (firstTNode = tNode); previousTNode ? (previousTNode.next = tNode) : (firstTNode = tNode);
previousTNode = tNode; previousTNode = tNode;
} }

View File

@ -54,7 +54,7 @@ export function defineComponent<T>(componentDefinition: {
/** /**
* Factory method used to create an instance of directive. * Factory method used to create an instance of directive.
*/ */
factory: () => T; factory: (t: Type<T>| null) => T;
/** /**
* The number of nodes, local refs, and pipes in this component template. * The number of nodes, local refs, and pipes in this component template.
@ -154,7 +154,7 @@ export function defineComponent<T>(componentDefinition: {
/** /**
* Function to create instances of content queries associated with a given directive. * Function to create instances of content queries associated with a given directive.
*/ */
contentQueries?: (() => void); contentQueries?: ((dirIndex: number) => void);
/** Refreshes content queries associated with directives in a given view */ /** Refreshes content queries associated with directives in a given view */
contentQueriesRefresh?: ((directiveIndex: number, queryIndex: number) => void); contentQueriesRefresh?: ((directiveIndex: number, queryIndex: number) => void);
@ -210,7 +210,7 @@ export function defineComponent<T>(componentDefinition: {
/** /**
* A list of optional features to apply. * A list of optional features to apply.
* *
* See: {@link NgOnChangesFeature}, {@link PublicFeature} * See: {@link NgOnChangesFeature}, {@link ProvidersFeature}
*/ */
features?: ComponentDefFeature[]; features?: ComponentDefFeature[];
@ -238,17 +238,6 @@ export function defineComponent<T>(componentDefinition: {
*/ */
changeDetection?: ChangeDetectionStrategy; changeDetection?: ChangeDetectionStrategy;
/**
* Defines the set of injectable objects that are visible to a Directive and its light DOM
* children.
*/
providers?: Provider[];
/**
* Defines the set of injectable objects that are visible to its view DOM children.
*/
viewProviders?: Provider[];
/** /**
* Registry of directives and components that may be found in this component's view. * Registry of directives and components that may be found in this component's view.
* *
@ -270,7 +259,7 @@ export function defineComponent<T>(componentDefinition: {
const declaredInputs: {[key: string]: string} = {} as any; const declaredInputs: {[key: string]: string} = {} as any;
const def: Mutable<ComponentDef<any>, keyof ComponentDef<any>> = { const def: Mutable<ComponentDef<any>, keyof ComponentDef<any>> = {
type: type, type: type,
diPublic: null, providersResolver: null,
consts: componentDefinition.consts, consts: componentDefinition.consts,
vars: componentDefinition.vars, vars: componentDefinition.vars,
hostVars: componentDefinition.hostVars || 0, hostVars: componentDefinition.hostVars || 0,
@ -301,8 +290,6 @@ export function defineComponent<T>(componentDefinition: {
// TODO(misko): convert ViewEncapsulation into const enum so that it can be used directly in the // TODO(misko): convert ViewEncapsulation into const enum so that it can be used directly in the
// next line. Also `None` should be 0 not 2. // next line. Also `None` should be 0 not 2.
encapsulation: componentDefinition.encapsulation || ViewEncapsulation.Emulated, encapsulation: componentDefinition.encapsulation || ViewEncapsulation.Emulated,
providers: EMPTY_ARRAY,
viewProviders: EMPTY_ARRAY,
id: 'c', id: 'c',
styles: componentDefinition.styles || EMPTY_ARRAY, styles: componentDefinition.styles || EMPTY_ARRAY,
_: null as never, _: null as never,
@ -525,7 +512,7 @@ export const defineDirective = defineComponent as any as<T>(directiveDefinition:
/** /**
* Factory method used to create an instance of directive. * Factory method used to create an instance of directive.
*/ */
factory: () => T; factory: (t: Type<T>| null) => T;
/** /**
* Static attributes to set on host element. * Static attributes to set on host element.
@ -595,7 +582,7 @@ export const defineDirective = defineComponent as any as<T>(directiveDefinition:
/** /**
* A list of optional features to apply. * A list of optional features to apply.
* *
* See: {@link NgOnChangesFeature}, {@link PublicFeature}, {@link InheritDefinitionFeature} * See: {@link NgOnChangesFeature}, {@link ProvidersFeature}, {@link InheritDefinitionFeature}
*/ */
features?: DirectiveDefFeature[]; features?: DirectiveDefFeature[];
@ -615,7 +602,7 @@ export const defineDirective = defineComponent as any as<T>(directiveDefinition:
/** /**
* Function to create instances of content queries associated with a given directive. * Function to create instances of content queries associated with a given directive.
*/ */
contentQueries?: (() => void); contentQueries?: ((directiveIndex: number) => void);
/** Refreshes content queries associated with directives in a given view */ /** Refreshes content queries associated with directives in a given view */
contentQueriesRefresh?: ((directiveIndex: number, queryIndex: number) => void); contentQueriesRefresh?: ((directiveIndex: number, queryIndex: number) => void);
@ -650,7 +637,7 @@ export function definePipe<T>(pipeDef: {
type: Type<T>, type: Type<T>,
/** A factory for creating a pipe instance. */ /** A factory for creating a pipe instance. */
factory: () => T, factory: (t: Type<T>| null) => T,
/** Whether the pipe is pure. */ /** Whether the pipe is pure. */
pure?: boolean pure?: boolean

View File

@ -6,23 +6,67 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
// We are temporarily importing the existing viewEngine_from core so we can be sure we are
// correctly implementing its interfaces for backwards compatibility.
import {getInjectableDef, getInjectorDef} from '../di/defs'; import {getInjectableDef, getInjectorDef} from '../di/defs';
import {InjectionToken} from '../di/injection_token'; import {InjectionToken} from '../di/injection_token';
import {InjectFlags, Injector, inject, setCurrentInjector} from '../di/injector'; import {InjectFlags, Injector, NullInjector, injectRootLimpMode, setInjectImplementation} from '../di/injector';
import {Type} from '../type'; import {Type} from '../type';
import {assertDefined} from './assert'; import {assertDefined, assertEqual} from './assert';
import {getComponentDef, getDirectiveDef, getPipeDef} from './definition'; import {getComponentDef, getDirectiveDef, getPipeDef} from './definition';
import {NG_ELEMENT_ID} from './fields'; import {NG_ELEMENT_ID} from './fields';
import {_getViewData, getPreviousOrParentTNode, resolveDirective, setEnvironment} from './instructions';
import {DirectiveDef} from './interfaces/definition'; import {DirectiveDef} from './interfaces/definition';
import {InjectorLocationFlags, PARENT_INJECTOR, TNODE,} from './interfaces/injector'; import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector';
import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType} from './interfaces/node'; import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType} from './interfaces/node';
import {DECLARATION_VIEW, HOST_NODE, INJECTOR, LViewData, TData, TVIEW, TView} from './interfaces/view'; import {DECLARATION_VIEW, HOST_NODE, INJECTOR, LViewData, TData, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert'; import {assertNodeOfPossibleTypes} from './node_assert';
import {getPreviousOrParentTNode, getViewData, setTNodeAndViewData} from './state';
import {getParentInjectorIndex, getParentInjectorView, getParentInjectorViewOffset, hasParentInjector, isComponent, stringify} from './util';
/**
* Defines if the call to `inject` should include `viewProviders` in its resolution.
*
* This is set to true when we try to instantiate a component. This value is reset in
* `getNodeInjectable` to a value which matches the declaration location of the token about to be
* instantiated. This is done so that if we are injecting a token which was declared outside of
* `viewProviders` we don't accidentally pull `viewProviders` in.
*
* Example:
*
* ```
* @Injectable()
* class MyService {
* constructor(public value: String) {}
* }
*
* @Component({
* providers: [
* MyService,
* {provide: String, value: 'providers' }
* ]
* viewProviders: [
* {provide: String, value: 'viewProviders'}
* ]
* })
* class MyComponent {
* constructor(myService: MyService, value: String) {
* // We expect that Component can see into `viewProviders`.
* expect(value).toEqual('viewProviders');
* // `MyService` was not declared in `viewProviders` hence it can't see it.
* expect(myService.value).toEqual('providers');
* }
* }
*
* ```
*/
let includeViewProviders = false;
function setIncludeViewProviders(v: boolean): boolean {
const oldValue = includeViewProviders;
includeViewProviders = v;
return oldValue;
}
/** /**
* The number of slots in each bloom filter (used by DI). The larger this number, the fewer * The number of slots in each bloom filter (used by DI). The larger this number, the fewer
@ -43,46 +87,40 @@ let nextNgElementId = 0;
* @param tView The TView for the injector's bloom filters * @param tView The TView for the injector's bloom filters
* @param type The directive token to register * @param type The directive token to register
*/ */
export function bloomAdd(injectorIndex: number, tView: TView, type: Type<any>): void { export function bloomAdd(
if (tView.firstTemplatePass) { injectorIndex: number, tView: TView, type: Type<any>| InjectionToken<any>): void {
let id: number|undefined = (type as any)[NG_ELEMENT_ID]; ngDevMode && assertEqual(tView.firstTemplatePass, true, 'expected firstTemplatePass to be true');
let id: number|undefined = (type as any)[NG_ELEMENT_ID];
// Set a unique ID on the directive type, so if something tries to inject the directive, // Set a unique ID on the directive type, so if something tries to inject the directive,
// we can easily retrieve the ID and hash it into the bloom bit that should be checked. // we can easily retrieve the ID and hash it into the bloom bit that should be checked.
if (id == null) { if (id == null) {
id = (type as any)[NG_ELEMENT_ID] = nextNgElementId++; id = (type as any)[NG_ELEMENT_ID] = nextNgElementId++;
}
// We only have BLOOM_SIZE (256) slots in our bloom filter (8 buckets * 32 bits each),
// so all unique IDs must be modulo-ed into a number from 0 - 255 to fit into the filter.
const bloomBit = id & BLOOM_MASK;
// Create a mask that targets the specific bit associated with the directive.
// JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding
// to bit positions 0 - 31 in a 32 bit integer.
const mask = 1 << bloomBit;
// Use the raw bloomBit number to determine which bloom filter bucket we should check
// e.g: bf0 = [0 - 31], bf1 = [32 - 63], bf2 = [64 - 95], bf3 = [96 - 127], etc
const b7 = bloomBit & 0x80;
const b6 = bloomBit & 0x40;
const b5 = bloomBit & 0x20;
const tData = tView.data as number[];
if (b7) {
b6 ? (b5 ? (tData[injectorIndex + 7] |= mask) : (tData[injectorIndex + 6] |= mask)) :
(b5 ? (tData[injectorIndex + 5] |= mask) : (tData[injectorIndex + 4] |= mask));
} else {
b6 ? (b5 ? (tData[injectorIndex + 3] |= mask) : (tData[injectorIndex + 2] |= mask)) :
(b5 ? (tData[injectorIndex + 1] |= mask) : (tData[injectorIndex] |= mask));
}
} }
}
export function getOrCreateNodeInjector(): number { // We only have BLOOM_SIZE (256) slots in our bloom filter (8 buckets * 32 bits each),
return getOrCreateNodeInjectorForNode( // so all unique IDs must be modulo-ed into a number from 0 - 255 to fit into the filter.
getPreviousOrParentTNode() as TElementNode | TElementContainerNode | TContainerNode, const bloomBit = id & BLOOM_MASK;
_getViewData());
// Create a mask that targets the specific bit associated with the directive.
// JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding
// to bit positions 0 - 31 in a 32 bit integer.
const mask = 1 << bloomBit;
// Use the raw bloomBit number to determine which bloom filter bucket we should check
// e.g: bf0 = [0 - 31], bf1 = [32 - 63], bf2 = [64 - 95], bf3 = [96 - 127], etc
const b7 = bloomBit & 0x80;
const b6 = bloomBit & 0x40;
const b5 = bloomBit & 0x20;
const tData = tView.data as number[];
if (b7) {
b6 ? (b5 ? (tData[injectorIndex + 7] |= mask) : (tData[injectorIndex + 6] |= mask)) :
(b5 ? (tData[injectorIndex + 5] |= mask) : (tData[injectorIndex + 4] |= mask));
} else {
b6 ? (b5 ? (tData[injectorIndex + 3] |= mask) : (tData[injectorIndex + 2] |= mask)) :
(b5 ? (tData[injectorIndex + 1] |= mask) : (tData[injectorIndex] |= mask));
}
} }
/** /**
@ -102,26 +140,29 @@ export function getOrCreateNodeInjectorForNode(
const tView = hostView[TVIEW]; const tView = hostView[TVIEW];
if (tView.firstTemplatePass) { if (tView.firstTemplatePass) {
tNode.injectorIndex = hostView.length; tNode.injectorIndex = hostView.length;
setUpBloom(tView.data, tNode); // foundation for node bloom insertBloom(tView.data, tNode); // foundation for node bloom
setUpBloom(hostView, null); // foundation for cumulative bloom insertBloom(hostView, null); // foundation for cumulative bloom
setUpBloom(tView.blueprint, null); insertBloom(tView.blueprint, null);
ngDevMode && assertEqual(
tNode.flags === 0 || tNode.flags === TNodeFlags.isComponent, true,
'expected tNode.flags to not be initialized');
} }
const parentLoc = getParentInjectorLocation(tNode, hostView); const parentLoc = getParentInjectorLocation(tNode, hostView);
const parentIndex = parentLoc & InjectorLocationFlags.InjectorIndexMask; const parentIndex = getParentInjectorIndex(parentLoc);
const parentView: LViewData = getParentInjectorView(parentLoc, hostView); const parentView: LViewData = getParentInjectorView(parentLoc, hostView);
const parentData = parentView[TVIEW].data as any;
const injectorIndex = tNode.injectorIndex; const injectorIndex = tNode.injectorIndex;
// If a parent injector can't be found, its location is set to -1. // If a parent injector can't be found, its location is set to -1.
// In that case, we don't need to set up a cumulative bloom // In that case, we don't need to set up a cumulative bloom
if (parentLoc !== -1) { if (hasParentInjector(parentLoc)) {
for (let i = 0; i < PARENT_INJECTOR; i++) { const parentData = parentView[TVIEW].data as any;
const bloomIndex = parentIndex + i; // Creates a cumulative bloom filter that merges the parent's bloom filter
// Creates a cumulative bloom filter that merges the parent's bloom filter // and its own cumulative bloom (which contains tokens for all ancestors)
// and its own cumulative bloom (which contains tokens for all ancestors) for (let i = 0; i < 8; i++) {
hostView[injectorIndex + i] = parentView[bloomIndex] | parentData[bloomIndex]; hostView[injectorIndex + i] = parentView[parentIndex + i] | parentData[parentIndex + i];
} }
} }
@ -129,10 +170,11 @@ export function getOrCreateNodeInjectorForNode(
return injectorIndex; return injectorIndex;
} }
function setUpBloom(arr: any[], footer: TNode | null) { function insertBloom(arr: any[], footer: TNode | null): void {
arr.push(0, 0, 0, 0, 0, 0, 0, 0, footer); arr.push(0, 0, 0, 0, 0, 0, 0, 0, footer);
} }
export function getInjectorIndex(tNode: TNode, hostView: LViewData): number { export function getInjectorIndex(tNode: TNode, hostView: LViewData): number {
if (tNode.injectorIndex === -1 || if (tNode.injectorIndex === -1 ||
// If the injector index is the same as its parent's injector index, then the index has been // If the injector index is the same as its parent's injector index, then the index has been
@ -150,10 +192,12 @@ export function getInjectorIndex(tNode: TNode, hostView: LViewData): number {
/** /**
* Finds the index of the parent injector, with a view offset if applicable. Used to set the * Finds the index of the parent injector, with a view offset if applicable. Used to set the
* parent injector initially. * parent injector initially.
*
* Returns a combination of number of `ViewData` we have to go up and index in that `Viewdata`
*/ */
export function getParentInjectorLocation(tNode: TNode, view: LViewData): number { export function getParentInjectorLocation(tNode: TNode, view: LViewData): RelativeInjectorLocation {
if (tNode.parent && tNode.parent.injectorIndex !== -1) { if (tNode.parent && tNode.parent.injectorIndex !== -1) {
return tNode.parent.injectorIndex; // view offset is 0 return tNode.parent.injectorIndex as any; // view offset is 0
} }
// For most cases, the parent injector index can be found on the host node (e.g. for component // For most cases, the parent injector index can be found on the host node (e.g. for component
@ -167,81 +211,20 @@ export function getParentInjectorLocation(tNode: TNode, view: LViewData): number
viewOffset++; viewOffset++;
} }
return hostTNode ? return hostTNode ?
hostTNode.injectorIndex | (viewOffset << InjectorLocationFlags.ViewOffsetShift) : hostTNode.injectorIndex | (viewOffset << RelativeInjectorLocationFlags.ViewOffsetShift) :
-1; -1 as any;
} }
/** /**
* Unwraps a parent injector location number to find the view offset from the current injector, * Makes a type or an injection token public to the DI system by adding it to an
* then walks up the declaration view tree until the view is found that contains the parent * injector's bloom filter.
* injector.
*
* @param location The location of the parent injector, which contains the view offset
* @param startView The LViewData instance from which to start walking up the view tree
* @returns The LViewData instance that contains the parent injector
*/
export function getParentInjectorView(location: number, startView: LViewData): LViewData {
let viewOffset = location >> InjectorLocationFlags.ViewOffsetShift;
let parentView = startView;
// For most cases, the parent injector can be found on the host node (e.g. for component
// or container), but we must keep the loop here to support the rarer case of deeply nested
// <ng-template> tags or inline views, where the parent injector might live many views
// above the child injector.
while (viewOffset > 0) {
parentView = parentView[DECLARATION_VIEW] !;
viewOffset--;
}
return parentView;
}
/**
* Makes a directive public to the DI system by adding it to an injector's bloom filter.
* *
* @param di The node injector in which a directive will be added * @param di The node injector in which a directive will be added
* @param def The definition of the directive to be made public * @param token The type or the injection token to be made public
*/ */
export function diPublicInInjector( export function diPublicInInjector(
injectorIndex: number, view: LViewData, def: DirectiveDef<any>): void { injectorIndex: number, view: LViewData, token: InjectionToken<any>| Type<any>): void {
bloomAdd(injectorIndex, view[TVIEW], def.type); bloomAdd(injectorIndex, view[TVIEW], token);
}
/**
* Makes a directive public to the DI system by adding it to an injector's bloom filter.
*
* @param def The definition of the directive to be made public
*/
export function diPublic(def: DirectiveDef<any>): void {
diPublicInInjector(getOrCreateNodeInjector(), _getViewData(), def);
}
/**
* Returns the value associated to the given token from the injectors.
*
* `directiveInject` is intended to be used for directive, component and pipe factories.
* All other injection use `inject` which does not walk the node injector tree.
*
* Usage example (in factory function):
*
* class SomeDirective {
* constructor(directive: DirectiveA) {}
*
* static ngDirectiveDef = defineDirective({
* type: SomeDirective,
* factory: () => new SomeDirective(directiveInject(DirectiveA))
* });
* }
*
* @param token the type or token to inject
* @param flags Injection flags
* @returns the value from the injector or `null` when not found
*/
export function directiveInject<T>(token: Type<T>| InjectionToken<T>): T;
export function directiveInject<T>(token: Type<T>| InjectionToken<T>, flags: InjectFlags): T;
export function directiveInject<T>(
token: Type<T>| InjectionToken<T>, flags = InjectFlags.Default): T|null {
const hostTNode =
getPreviousOrParentTNode() as TElementNode | TContainerNode | TElementContainerNode;
return getOrCreateInjectable<T>(hostTNode, _getViewData(), token, flags);
} }
/** /**
@ -275,8 +258,7 @@ export function directiveInject<T>(
* *
* @publicApi * @publicApi
*/ */
export function injectAttribute(attrNameToInject: string): string|undefined { export function injectAttributeImpl(tNode: TNode, attrNameToInject: string): string|undefined {
const tNode = getPreviousOrParentTNode();
ngDevMode && assertNodeOfPossibleTypes( ngDevMode && assertNodeOfPossibleTypes(
tNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer); tNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
ngDevMode && assertDefined(tNode, 'expecting tNode'); ngDevMode && assertDefined(tNode, 'expecting tNode');
@ -295,7 +277,7 @@ export function injectAttribute(attrNameToInject: string): string|undefined {
/** /**
* Returns the value associated to the given token from the injectors. * Returns the value associated to the given token from the NodeInjectors => ModuleInjector.
* *
* Look for the injector providing the token by walking up the node injector tree and then * Look for the injector providing the token by walking up the node injector tree and then
* the module injector tree. * the module injector tree.
@ -306,133 +288,169 @@ export function injectAttribute(attrNameToInject: string): string|undefined {
* @returns the value from the injector or `null` when not found * @returns the value from the injector or `null` when not found
*/ */
export function getOrCreateInjectable<T>( export function getOrCreateInjectable<T>(
hostTNode: TElementNode | TContainerNode | TElementContainerNode, hostView: LViewData, tNode: TElementNode | TContainerNode | TElementContainerNode, lViewData: LViewData,
token: Type<T>| InjectionToken<T>, flags: InjectFlags = InjectFlags.Default): T|null { token: Type<T>| InjectionToken<T>, flags: InjectFlags = InjectFlags.Default,
notFoundValue?: any): T|null {
const bloomHash = bloomHashBitOrFactory(token); const bloomHash = bloomHashBitOrFactory(token);
// If the ID stored here is a function, this is a special object like ElementRef or TemplateRef // If the ID stored here is a function, this is a special object like ElementRef or TemplateRef
// so just call the factory function to create it. // so just call the factory function to create it.
if (typeof bloomHash === 'function') return bloomHash(); if (typeof bloomHash === 'function') {
const savePreviousOrParentTNode = getPreviousOrParentTNode();
const saveViewData = getViewData();
setTNodeAndViewData(tNode, lViewData);
try {
return bloomHash();
} finally {
setTNodeAndViewData(savePreviousOrParentTNode, saveViewData);
}
} else if (typeof bloomHash == 'number') {
// If the token has a bloom hash, then it is a token which could be in NodeInjector.
// If the token has a bloom hash, then it is a directive that is public to the injection system // A reference to the previous injector TView that was found while climbing the element injector
// (diPublic) otherwise fall back to the module injector. // tree. This is used to know if viewProviders can be accessed on the current injector.
if (bloomHash != null) { let previousTView: TView|null = null;
const startInjectorIndex = getInjectorIndex(hostTNode, hostView); let injectorIndex = getInjectorIndex(tNode, lViewData);
let parentLocation: RelativeInjectorLocation = NO_PARENT_INJECTOR;
let injectorIndex = startInjectorIndex; // If we should skip this injector, start by searching the parent injector.
let injectorView = hostView; if (flags & InjectFlags.SkipSelf) {
let parentLocation: number = -1; parentLocation = injectorIndex === -1 ? getParentInjectorLocation(tNode, lViewData) :
lViewData[injectorIndex + PARENT_INJECTOR];
// If we should skip this injector or if an injector doesn't exist on this node (e.g. all if (!shouldSearchParent(flags, parentLocation)) {
// directives on this node are private), start by searching the parent injector.
if (flags & InjectFlags.SkipSelf || injectorIndex === -1) {
parentLocation = injectorIndex === -1 ? getParentInjectorLocation(hostTNode, hostView) :
injectorView[injectorIndex + PARENT_INJECTOR];
if (shouldNotSearchParent(flags, parentLocation)) {
injectorIndex = -1; injectorIndex = -1;
} else { } else {
injectorIndex = parentLocation & InjectorLocationFlags.InjectorIndexMask; previousTView = lViewData[TVIEW];
injectorView = getParentInjectorView(parentLocation, injectorView); injectorIndex = getParentInjectorIndex(parentLocation);
lViewData = getParentInjectorView(parentLocation, lViewData);
} }
} }
// Traverse up the injector tree until we find a potential match or until we know there
// *isn't* a match.
while (injectorIndex !== -1) { while (injectorIndex !== -1) {
// Traverse up the injector tree until we find a potential match or until we know there parentLocation = lViewData[injectorIndex + PARENT_INJECTOR];
// *isn't* a match. Outer loop is necessary in case we get a false positive injector.
while (injectorIndex !== -1) {
// Check the current injector. If it matches, stop searching for an injector.
if (injectorHasToken(bloomHash, injectorIndex, injectorView[TVIEW].data)) {
break;
}
parentLocation = injectorView[injectorIndex + PARENT_INJECTOR]; // Check the current injector. If it matches, see if it contains token.
if (shouldNotSearchParent(flags, parentLocation)) { const tView = lViewData[TVIEW];
injectorIndex = -1; if (bloomHasToken(bloomHash, injectorIndex, tView.data)) {
break; // At this point, we have an injector which *may* contain the token, so we step through
} // the providers and directives associated with the injector's corresponding node to get
// the instance.
// If the ancestor bloom filter value has the bit corresponding to the directive, traverse const instance: T|null =
// up to find the specific injector. If the ancestor bloom filter does not have the bit, we searchTokensOnInjector<T>(injectorIndex, lViewData, token, previousTView);
// can abort. if (instance !== NOT_FOUND) {
if (injectorHasToken(bloomHash, injectorIndex, injectorView)) { return instance;
injectorIndex = parentLocation & InjectorLocationFlags.InjectorIndexMask;
injectorView = getParentInjectorView(parentLocation, injectorView);
} else {
injectorIndex = -1;
break;
} }
} }
if (shouldSearchParent(flags, parentLocation) &&
// If no injector is found, we *know* that there is no ancestor injector that contains the bloomHasToken(bloomHash, injectorIndex, lViewData)) {
// token, so we abort. // The def wasn't found anywhere on this node, so it was a false positive.
if (injectorIndex === -1) { // Traverse up the tree and continue searching.
break; previousTView = tView;
injectorIndex = getParentInjectorIndex(parentLocation);
lViewData = getParentInjectorView(parentLocation, lViewData);
} else {
// If we should not search parent OR If the ancestor bloom filter value does not have the
// bit corresponding to the directive we can give up on traversing up to find the specific
// injector.
injectorIndex = -1;
} }
// At this point, we have an injector which *may* contain the token, so we step through the
// directives associated with the injector's corresponding node to get the directive instance.
let instance: T|null;
if (instance = searchDirectivesOnInjector<T>(injectorIndex, injectorView, token)) {
return instance;
}
// If we *didn't* find the directive for the token and we are searching the current node's
// injector, it's possible the directive is on this node and hasn't been created yet.
if (injectorIndex === startInjectorIndex && hostView === injectorView &&
(instance = searchMatchesQueuedForCreation<T>(token, injectorView[TVIEW]))) {
return instance;
}
// The def wasn't found anywhere on this node, so it was a false positive.
// Traverse up the tree and continue searching.
injectorIndex = parentLocation & InjectorLocationFlags.InjectorIndexMask;
injectorView = getParentInjectorView(parentLocation, injectorView);
} }
} }
const moduleInjector = hostView[INJECTOR]; if ((flags & (InjectFlags.Self | InjectFlags.Host)) === 0) {
const formerInjector = setCurrentInjector(moduleInjector); const moduleInjector = lViewData[INJECTOR];
try { if (moduleInjector) {
return inject(token, flags); return moduleInjector.get(token, notFoundValue, flags & InjectFlags.Optional);
} finally { } else {
setCurrentInjector(formerInjector); return injectRootLimpMode(token, notFoundValue, flags & InjectFlags.Optional);
}
}
function searchMatchesQueuedForCreation<T>(token: any, hostTView: TView): T|null {
const matches = hostTView.currentMatches;
if (matches) {
for (let i = 0; i < matches.length; i += 2) {
const def = matches[i] as DirectiveDef<any>;
if (def.type === token) {
return resolveDirective(def, i + 1, matches);
}
} }
} }
return null; if (flags & InjectFlags.Optional) {
return notFoundValue;
} else {
throw new Error(`NodeInjector: NOT_FOUND [${stringify(token)}]`);
}
} }
function searchDirectivesOnInjector<T>( const NOT_FOUND = {};
injectorIndex: number, injectorView: LViewData, token: Type<T>| InjectionToken<T>) {
const tNode = injectorView[TVIEW].data[injectorIndex + TNODE] as TNode; function searchTokensOnInjector<T>(
injectorIndex: number, injectorView: LViewData, token: Type<T>| InjectionToken<T>,
previousTView: TView | null) {
const currentTView = injectorView[TVIEW];
const tNode = currentTView.data[injectorIndex + TNODE] as TNode;
const nodeFlags = tNode.flags; const nodeFlags = tNode.flags;
const count = nodeFlags & TNodeFlags.DirectiveCountMask; const nodeProviderIndexes = tNode.providerIndexes;
const tInjectables = currentTView.data;
if (count !== 0) { // First, we step through providers
const start = nodeFlags >> TNodeFlags.DirectiveStartingIndexShift; let canAccessViewProviders = false;
const end = start + count; // We need to determine if view providers can be accessed by the starting element.
const defs = injectorView[TVIEW].data; // It happens in 2 cases:
// 1) On the initial element injector , if we are instantiating a token which can see the
for (let i = start; i < end; i++) { // viewProviders of the component of that element. Such token are:
// Get the definition for the directive at this index and, if it is injectable (diPublic), // - the component itself (but not other directives)
// and matches the given token, return the directive instance. // - viewProviders tokens of the component (but not providers tokens)
const directiveDef = defs[i] as DirectiveDef<any>; // 2) Upper in the element injector tree, if the starting element is actually in the view of
if (directiveDef.type === token && directiveDef.diPublic) { // the current element. To determine this, we track the transition of view during the climb,
return injectorView[i]; // and check the host node of the current view to identify component views.
} if (previousTView == null && isComponent(tNode) && includeViewProviders ||
previousTView != null && previousTView != currentTView &&
(currentTView.node == null || currentTView.node !.type === TNodeType.Element)) {
canAccessViewProviders = true;
}
const startInjectables = nodeProviderIndexes & TNodeProviderIndexes.ProvidersStartIndexMask;
const startDirectives = nodeFlags >> TNodeFlags.DirectiveStartingIndexShift;
const cptViewProvidersCount =
nodeProviderIndexes >> TNodeProviderIndexes.CptViewProvidersCountShift;
const startingIndex =
canAccessViewProviders ? startInjectables : startInjectables + cptViewProvidersCount;
const directiveCount = nodeFlags & TNodeFlags.DirectiveCountMask;
for (let i = startingIndex; i < startDirectives + directiveCount; i++) {
const providerTokenOrDef = tInjectables[i] as InjectionToken<any>| Type<any>| DirectiveDef<any>;
if (i < startDirectives && token === providerTokenOrDef ||
i >= startDirectives && (providerTokenOrDef as DirectiveDef<any>).type === token) {
return getNodeInjectable(tInjectables, injectorView, i, tNode as TElementNode);
} }
} }
return null; return NOT_FOUND;
}
/**
* Retrieve or instantiate the injectable from the `lData` at particular `index`.
*
* This function checks to see if the value has already been instantiated and if so returns the
* cached `injectable`. Otherwise if it detects that the value is still a factory it
* instantiates the `injectable` and caches the value.
*/
export function getNodeInjectable(
tData: TData, lData: LViewData, index: number, tNode: TElementNode): any {
let value = lData[index];
if (isFactory(value)) {
const factory: NodeInjectorFactory = value;
if (factory.resolving) {
throw new Error(`Circular dep for ${stringify(tData[index])}`);
}
const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);
factory.resolving = true;
let previousInjectImplementation;
if (factory.injectImpl) {
previousInjectImplementation = setInjectImplementation(factory.injectImpl);
}
const savePreviousOrParentTNode = getPreviousOrParentTNode();
const saveViewData = getViewData();
setTNodeAndViewData(tNode, lData);
try {
value = lData[index] = factory.factory(null, tData, lData, tNode);
} finally {
if (factory.injectImpl) setInjectImplementation(previousInjectImplementation);
setIncludeViewProviders(previousIncludeViewProviders);
factory.resolving = false;
setTNodeAndViewData(savePreviousOrParentTNode, saveViewData);
}
}
return value;
} }
/** /**
@ -452,7 +470,7 @@ export function bloomHashBitOrFactory(token: Type<any>| InjectionToken<any>): nu
return typeof tokenId === 'number' ? tokenId & BLOOM_MASK : tokenId; return typeof tokenId === 'number' ? tokenId & BLOOM_MASK : tokenId;
} }
export function injectorHasToken( export function bloomHasToken(
bloomHash: number, injectorIndex: number, injectorView: LViewData | TData) { bloomHash: number, injectorIndex: number, injectorView: LViewData | TData) {
// Create a mask that targets the specific bit associated with the directive we're looking for. // Create a mask that targets the specific bit associated with the directive we're looking for.
// JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding
@ -481,26 +499,14 @@ export function injectorHasToken(
} }
/** Returns true if flags prevent parent injector from being searched for tokens */ /** Returns true if flags prevent parent injector from being searched for tokens */
function shouldNotSearchParent(flags: InjectFlags, parentLocation: number): boolean|number { function shouldSearchParent(flags: InjectFlags, parentLocation: RelativeInjectorLocation): boolean|
return flags & InjectFlags.Self || number {
(flags & InjectFlags.Host && (parentLocation >> InjectorLocationFlags.ViewOffsetShift) > 0); return !(
flags & InjectFlags.Self ||
(flags & InjectFlags.Host && getParentInjectorViewOffset(parentLocation) > 0));
} }
export class NodeInjector implements Injector { export function getFactoryOf<T>(type: Type<any>): ((type: Type<T>| null) => T)|null {
private _injectorIndex: number;
constructor(
private _tNode: TElementNode|TContainerNode|TElementContainerNode,
private _hostView: LViewData) {
this._injectorIndex = getOrCreateNodeInjectorForNode(_tNode, _hostView);
}
get(token: any): any {
setEnvironment(this._tNode, this._hostView);
return getOrCreateInjectable(this._tNode, this._hostView, token);
}
}
export function getFactoryOf<T>(type: Type<any>): ((type?: Type<T>) => T)|null {
const typeAny = type as any; const typeAny = type as any;
const def = getComponentDef<T>(typeAny) || getDirectiveDef<T>(typeAny) || const def = getComponentDef<T>(typeAny) || getDirectiveDef<T>(typeAny) ||
getPipeDef<T>(typeAny) || getInjectableDef<T>(typeAny) || getInjectorDef<T>(typeAny); getPipeDef<T>(typeAny) || getInjectableDef<T>(typeAny) || getInjectorDef<T>(typeAny);

View File

@ -0,0 +1,260 @@
/*
* @license
* Copyright Google Inc. All Rights Reserved.
*
* 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 {resolveForwardRef} from '../di/forward_ref';
import {Provider} from '../di/provider';
import {isTypeProvider, providerToFactory} from '../di/r3_injector';
import {DirectiveDef} from '.';
import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} from './di';
import {directiveInject} from './instructions';
import {NodeInjectorFactory} from './interfaces/injector';
import {TContainerNode, TElementContainerNode, TElementNode, TNodeFlags, TNodeProviderIndexes} from './interfaces/node';
import {LViewData, TData, TVIEW, TView} from './interfaces/view';
import {getPreviousOrParentTNode, getViewData} from './state';
import {isComponentDef} from './util';
/**
* Resolves the providers which are defined in the DirectiveDef.
*
* When inserting the tokens and the factories in their respective arrays, we can assume that
* this method is called first for the component (if any), and then for other directives on the same
* node.
* As a consequence,the providers are always processed in that order:
* 1) The view providers of the component
* 2) The providers of the component
* 3) The providers of the other directives
* This matches the structure of the injectables arrays of a view (for each node).
* So the tokens and the factories can be pushed at the end of the arrays, except
* in one case for multi providers.
*
* @param def the directive definition
* @param providers: Array of `providers`.
* @param viewProviders: Array of `viewProviders`.
*/
export function providersResolver<T>(
def: DirectiveDef<T>, providers: Provider[], viewProviders: Provider[]): void {
const viewData = getViewData();
const tView: TView = viewData[TVIEW];
if (tView.firstTemplatePass) {
const isComponent = isComponentDef(def);
// The list of view providers is processed first, and the flags are updated
resolveProvider(viewProviders, tView.data, tView.blueprint, isComponent, true);
// Then, the list of providers is processed, and the flags are updated
resolveProvider(providers, tView.data, tView.blueprint, isComponent, false);
}
}
/**
* Resolves a provider and publishes it to the DI system.
*/
function resolveProvider(
provider: Provider, tInjectables: TData, lInjectablesBlueprint: NodeInjectorFactory[],
isComponent: boolean, isViewProvider: boolean): void {
provider = resolveForwardRef(provider);
if (Array.isArray(provider)) {
// Recursively call `resolveProvider`
// Recursion is OK in this case because this code will not be in hot-path once we implement
// cloning of the initial state.
for (let i = 0; i < provider.length; i++) {
resolveProvider(
provider[i], tInjectables, lInjectablesBlueprint, isComponent, isViewProvider);
}
} else {
const viewData = getViewData();
let token: any = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide);
let providerFactory: () => any = providerToFactory(provider);
const previousOrParentTNode = getPreviousOrParentTNode();
const beginIndex =
previousOrParentTNode.providerIndexes & TNodeProviderIndexes.ProvidersStartIndexMask;
const endIndex = previousOrParentTNode.flags >> TNodeFlags.DirectiveStartingIndexShift;
const cptViewProvidersCount =
previousOrParentTNode.providerIndexes >> TNodeProviderIndexes.CptViewProvidersCountShift;
if (isTypeProvider(provider) || !provider.multi) {
// Single provider case: the factory is created and pushed immediately
const factory = new NodeInjectorFactory(providerFactory, isViewProvider, directiveInject);
const existingFactoryIndex = indexOf(
token, tInjectables, isViewProvider ? beginIndex : beginIndex + cptViewProvidersCount,
endIndex);
if (existingFactoryIndex == -1) {
diPublicInInjector(
getOrCreateNodeInjectorForNode(
previousOrParentTNode as TElementNode | TContainerNode | TElementContainerNode,
viewData),
viewData, token);
tInjectables.push(token);
previousOrParentTNode.flags += 1 << TNodeFlags.DirectiveStartingIndexShift;
if (isViewProvider) {
previousOrParentTNode.providerIndexes +=
TNodeProviderIndexes.CptViewProvidersCountShifter;
}
lInjectablesBlueprint.push(factory);
viewData.push(factory);
} else {
lInjectablesBlueprint[existingFactoryIndex] = factory;
viewData[existingFactoryIndex] = factory;
}
} else {
// Multi provider case:
// We create a multi factory which is going to aggregate all the values.
// Since the output of such a factory depends on content or view injection,
// we create two of them, which are linked together.
//
// The first one (for view providers) is always in the first block of the injectables array,
// and the second one (for providers) is always in the second block.
// This is important because view providers have higher priority. When a multi token
// is being looked up, the view providers should be found first.
// Note that it is not possible to have a multi factory in the third block (directive block).
//
// The algorithm to process multi providers is as follows:
// 1) If the multi provider comes from the `viewProviders` of the component:
// a) If the special view providers factory doesn't exist, it is created and pushed.
// b) Else, the multi provider is added to the existing multi factory.
// 2) If the multi provider comes from the `providers` of the component or of another
// directive:
// a) If the multi factory doesn't exist, it is created and provider pushed into it.
// It is also linked to the multi factory for view providers, if it exists.
// b) Else, the multi provider is added to the existing multi factory.
const existingProvidersFactoryIndex =
indexOf(token, tInjectables, beginIndex + cptViewProvidersCount, endIndex);
const existingViewProvidersFactoryIndex =
indexOf(token, tInjectables, beginIndex, beginIndex + cptViewProvidersCount);
const doesProvidersFactoryExist = existingProvidersFactoryIndex >= 0 &&
lInjectablesBlueprint[existingProvidersFactoryIndex];
const doesViewProvidersFactoryExist = existingViewProvidersFactoryIndex >= 0 &&
lInjectablesBlueprint[existingViewProvidersFactoryIndex];
if (isViewProvider && !doesViewProvidersFactoryExist ||
!isViewProvider && !doesProvidersFactoryExist) {
// Cases 1.a and 2.a
diPublicInInjector(
getOrCreateNodeInjectorForNode(
previousOrParentTNode as TElementNode | TContainerNode | TElementContainerNode,
viewData),
viewData, token);
const factory = multiFactory(
isViewProvider ? multiViewProvidersFactoryResolver : multiProvidersFactoryResolver,
lInjectablesBlueprint.length, isViewProvider, isComponent, providerFactory);
if (!isViewProvider && doesViewProvidersFactoryExist) {
lInjectablesBlueprint[existingViewProvidersFactoryIndex].providerFactory = factory;
}
tInjectables.push(token);
previousOrParentTNode.flags += 1 << TNodeFlags.DirectiveStartingIndexShift;
if (isViewProvider) {
previousOrParentTNode.providerIndexes +=
TNodeProviderIndexes.CptViewProvidersCountShifter;
}
lInjectablesBlueprint.push(factory);
viewData.push(factory);
} else {
// Cases 1.b and 2.b
multiFactoryAdd(
lInjectablesBlueprint ![isViewProvider ? existingViewProvidersFactoryIndex : existingProvidersFactoryIndex],
providerFactory, !isViewProvider && isComponent);
}
if (!isViewProvider && isComponent && doesViewProvidersFactoryExist) {
lInjectablesBlueprint[existingViewProvidersFactoryIndex].componentProviders !++;
}
}
}
}
/**
* Add a factory in a multi factory.
*/
function multiFactoryAdd(
multiFactory: NodeInjectorFactory, factory: () => any, isComponentProvider: boolean): void {
multiFactory.multi !.push(factory);
if (isComponentProvider) {
multiFactory.componentProviders !++;
}
}
/**
* Returns the index of item in the array, but only in the begin to end range.
*/
function indexOf(item: any, arr: any[], begin: number, end: number) {
for (let i = begin; i < end; i++) {
if (arr[i] === item) return i;
}
return -1;
}
/**
* Use this with `multi` `providers`.
*/
function multiProvidersFactoryResolver(
this: NodeInjectorFactory, _: null, tData: TData, lData: LViewData,
tNode: TElementNode): any[] {
return multiResolve(this.multi !, []);
}
/**
* Use this with `multi` `viewProviders`.
*
* This factory knows how to concatenate itself with the existing `multi` `providers`.
*/
function multiViewProvidersFactoryResolver(
this: NodeInjectorFactory, _: null, tData: TData, lData: LViewData,
tNode: TElementNode): any[] {
const factories = this.multi !;
let result: any[];
if (this.providerFactory) {
const componentCount = this.providerFactory.componentProviders !;
const multiProviders = getNodeInjectable(tData, lData, this.providerFactory !.index !, tNode);
// Copy the section of the array which contains `multi` `providers` from the component
result = multiProviders.slice(0, componentCount);
// Insert the `viewProvider` instances.
multiResolve(factories, result);
// Copy the section of the array which contains `multi` `providers` from other directives
for (let i = componentCount; i < multiProviders.length; i++) {
result.push(multiProviders[i]);
}
} else {
result = [];
// Insert the `viewProvider` instances.
multiResolve(factories, result);
}
return result;
}
/**
* Maps an array of factories into an array of values.
*/
function multiResolve(factories: Array<() => any>, result: any[]): any[] {
for (let i = 0; i < factories.length; i++) {
const factory = factories[i] !as() => null;
result.push(factory());
}
return result;
}
/**
* Creates a multi factory.
*/
function multiFactory(
factoryFn:
(this: NodeInjectorFactory, _: null, tData: TData, lData: LViewData, tNode: TElementNode) =>
any,
index: number, isViewProvider: boolean, isComponent: boolean,
f: () => any): NodeInjectorFactory {
const factory = new NodeInjectorFactory(factoryFn, isViewProvider, directiveInject);
factory.multi = [];
factory.index = index;
factory.componentProviders = 0;
multiFactoryAdd(factory, f, isComponent && !isViewProvider);
return factory;
}

View File

@ -9,11 +9,12 @@ import {Injector} from '../di/injector';
import {assertDefined} from './assert'; import {assertDefined} from './assert';
import {discoverDirectives, discoverLocalRefs, getContext, isComponentInstance} from './context_discovery'; import {discoverDirectives, discoverLocalRefs, getContext, isComponentInstance} from './context_discovery';
import {NodeInjector} from './di';
import {LContext} from './interfaces/context'; import {LContext} from './interfaces/context';
import {TElementNode, TNode, TNodeFlags} from './interfaces/node'; import {TElementNode, TNode, TNodeFlags} from './interfaces/node';
import {CONTEXT, FLAGS, LViewData, LViewFlags, PARENT, RootContext, TVIEW} from './interfaces/view'; import {CONTEXT, FLAGS, LViewData, LViewFlags, PARENT, RootContext, TVIEW} from './interfaces/view';
import {getComponentViewByIndex, readPatchedLViewData} from './util'; import {getComponentViewByIndex, readPatchedLViewData} from './util';
import {NodeInjector} from './view_engine_compatibility';
/** /**

View File

@ -102,9 +102,9 @@ export function InheritDefinitionFeature(definition: DirectiveDef<any>| Componen
const superContentQueries = superDef.contentQueries; const superContentQueries = superDef.contentQueries;
if (superContentQueries) { if (superContentQueries) {
if (prevContentQueries) { if (prevContentQueries) {
definition.contentQueries = () => { definition.contentQueries = (dirIndex: number) => {
superContentQueries(); superContentQueries(dirIndex);
prevContentQueries(); prevContentQueries(dirIndex);
}; };
} else { } else {
definition.contentQueries = superContentQueries; definition.contentQueries = superContentQueries;

View File

@ -0,0 +1,45 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* 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 {Provider} from '../../di/provider';
import {providersResolver} from '../di_setup';
import {DirectiveDef} from '../interfaces/definition';
/**
* This feature resolves the providers of a directive (or component),
* and publish them into the DI system, making it visible to others for injection.
*
* For example:
* class ComponentWithProviders {
* constructor(private greeter: GreeterDE) {}
*
* static ngComponentDef = defineComponent({
* type: ComponentWithProviders,
* selectors: [['component-with-providers']],
* factory: () => new ComponentWithProviders(directiveInject(GreeterDE as any)),
* consts: 1,
* vars: 1,
* template: function(fs: RenderFlags, ctx: ComponentWithProviders) {
* if (fs & RenderFlags.Create) {
* text(0);
* }
* if (fs & RenderFlags.Update) {
* textBinding(0, bind(ctx.greeter.greet()));
* }
* },
* features: [ProvidersFeature([GreeterDE])]
* });
* }
*
* @param definition
*/
export function ProvidersFeature<T>(providers: Provider[], viewProviders: Provider[] = []) {
return (definition: DirectiveDef<T>) => {
definition.providersResolver = (def: DirectiveDef<T>) =>
providersResolver(def, providers, viewProviders);
};
}

View File

@ -1,19 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* 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 {diPublic} from '../di';
import {DirectiveDef} from '../interfaces/definition';
/**
* This feature publishes the directive (or component) into the DI system, making it visible to
* others for injection.
*
* @param definition
*/
export function PublicFeature<T>(definition: DirectiveDef<T>) {
definition.diPublic = diPublic;
}

View File

@ -9,13 +9,14 @@
import {NO_CHANGE} from '../../src/render3/tokens'; import {NO_CHANGE} from '../../src/render3/tokens';
import {assertEqual, assertLessThan} from './assert'; import {assertEqual, assertLessThan} from './assert';
import {_getViewData, adjustBlueprintForNewNode, bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4, createNodeAtIndex, getRenderer, load, resetComponentState} from './instructions'; import {adjustBlueprintForNewNode, bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4, createNodeAtIndex, load} from './instructions';
import {LContainer, NATIVE, RENDER_PARENT} from './interfaces/container'; import {LContainer, NATIVE, RENDER_PARENT} from './interfaces/container';
import {TElementNode, TNode, TNodeType} from './interfaces/node'; import {TElementNode, TNode, TNodeType} from './interfaces/node';
import {RComment, RElement} from './interfaces/renderer'; import {RComment, RElement} from './interfaces/renderer';
import {StylingContext} from './interfaces/styling'; import {StylingContext} from './interfaces/styling';
import {BINDING_INDEX, HEADER_OFFSET, HOST_NODE, TVIEW} from './interfaces/view'; import {BINDING_INDEX, HEADER_OFFSET, HOST_NODE, TVIEW} from './interfaces/view';
import {appendChild, createTextNode, removeChild} from './node_manipulation'; import {appendChild, createTextNode, removeChild} from './node_manipulation';
import {getRenderer, getViewData, resetComponentState} from './state';
import {getNativeByIndex, getNativeByTNode, getTNode, isLContainer, stringify} from './util'; import {getNativeByIndex, getNativeByTNode, getTNode, isLContainer, stringify} from './util';
@ -256,7 +257,7 @@ function appendI18nNode(tNode: TNode, parentTNode: TNode, previousTNode: TNode):
ngDevMode.rendererMoveNode++; ngDevMode.rendererMoveNode++;
} }
const viewData = _getViewData(); const viewData = getViewData();
// On first pass, re-organize node tree to put this node in the correct position. // On first pass, re-organize node tree to put this node in the correct position.
const firstTemplatePass = viewData[TVIEW].firstTemplatePass; const firstTemplatePass = viewData[TVIEW].firstTemplatePass;
@ -311,7 +312,7 @@ export function i18nEnd(): void {
* @param instructions The list of instructions to apply on the current view. * @param instructions The list of instructions to apply on the current view.
*/ */
export function i18nApply(startIndex: number, instructions: I18nInstruction[]): void { export function i18nApply(startIndex: number, instructions: I18nInstruction[]): void {
const viewData = _getViewData(); const viewData = getViewData();
if (ngDevMode) { if (ngDevMode) {
assertEqual( assertEqual(
viewData[BINDING_INDEX], viewData[TVIEW].bindingStartIndex, viewData[BINDING_INDEX], viewData[TVIEW].bindingStartIndex,
@ -411,7 +412,7 @@ export function i18nExpMapping(
* @returns The concatenated string when any of the arguments changes, `NO_CHANGE` otherwise. * @returns The concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.
*/ */
export function i18nInterpolation1(instructions: I18nExpInstruction[], v0: any): string|NO_CHANGE { export function i18nInterpolation1(instructions: I18nExpInstruction[], v0: any): string|NO_CHANGE {
const different = bindingUpdated(_getViewData()[BINDING_INDEX]++, v0); const different = bindingUpdated(getViewData()[BINDING_INDEX]++, v0);
if (!different) { if (!different) {
return NO_CHANGE; return NO_CHANGE;
@ -442,7 +443,7 @@ export function i18nInterpolation1(instructions: I18nExpInstruction[], v0: any):
*/ */
export function i18nInterpolation2(instructions: I18nExpInstruction[], v0: any, v1: any): string| export function i18nInterpolation2(instructions: I18nExpInstruction[], v0: any, v1: any): string|
NO_CHANGE { NO_CHANGE {
const viewData = _getViewData(); const viewData = getViewData();
const different = bindingUpdated2(viewData[BINDING_INDEX], v0, v1); const different = bindingUpdated2(viewData[BINDING_INDEX], v0, v1);
viewData[BINDING_INDEX] += 2; viewData[BINDING_INDEX] += 2;
@ -482,7 +483,7 @@ export function i18nInterpolation2(instructions: I18nExpInstruction[], v0: any,
*/ */
export function i18nInterpolation3( export function i18nInterpolation3(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any): string|NO_CHANGE { instructions: I18nExpInstruction[], v0: any, v1: any, v2: any): string|NO_CHANGE {
const viewData = _getViewData(); const viewData = getViewData();
const different = bindingUpdated3(viewData[BINDING_INDEX], v0, v1, v2); const different = bindingUpdated3(viewData[BINDING_INDEX], v0, v1, v2);
viewData[BINDING_INDEX] += 3; viewData[BINDING_INDEX] += 3;
@ -524,7 +525,7 @@ export function i18nInterpolation3(
*/ */
export function i18nInterpolation4( export function i18nInterpolation4(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any): string|NO_CHANGE { instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any): string|NO_CHANGE {
const viewData = _getViewData(); const viewData = getViewData();
const different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3); const different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
viewData[BINDING_INDEX] += 4; viewData[BINDING_INDEX] += 4;
@ -568,7 +569,7 @@ export function i18nInterpolation4(
export function i18nInterpolation5( export function i18nInterpolation5(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any): string| instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any): string|
NO_CHANGE { NO_CHANGE {
const viewData = _getViewData(); const viewData = getViewData();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3); let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated(viewData[BINDING_INDEX] + 4, v4) || different; different = bindingUpdated(viewData[BINDING_INDEX] + 4, v4) || different;
viewData[BINDING_INDEX] += 5; viewData[BINDING_INDEX] += 5;
@ -615,7 +616,7 @@ export function i18nInterpolation5(
i18nInterpolation6( i18nInterpolation6(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any, v5: any): instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any, v5: any):
string|NO_CHANGE { string|NO_CHANGE {
const viewData = _getViewData(); const viewData = getViewData();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3); let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated2(viewData[BINDING_INDEX] + 4, v4, v5) || different; different = bindingUpdated2(viewData[BINDING_INDEX] + 4, v4, v5) || different;
viewData[BINDING_INDEX] += 6; viewData[BINDING_INDEX] += 6;
@ -663,7 +664,7 @@ i18nInterpolation6(
export function i18nInterpolation7( export function i18nInterpolation7(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any, v5: any,
v6: any): string|NO_CHANGE { v6: any): string|NO_CHANGE {
const viewData = _getViewData(); const viewData = getViewData();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3); let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated3(viewData[BINDING_INDEX] + 4, v4, v5, v6) || different; different = bindingUpdated3(viewData[BINDING_INDEX] + 4, v4, v5, v6) || different;
viewData[BINDING_INDEX] += 7; viewData[BINDING_INDEX] += 7;
@ -712,7 +713,7 @@ export function i18nInterpolation7(
export function i18nInterpolation8( export function i18nInterpolation8(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any, v5: any,
v6: any, v7: any): string|NO_CHANGE { v6: any, v7: any): string|NO_CHANGE {
const viewData = _getViewData(); const viewData = getViewData();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3); let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated4(viewData[BINDING_INDEX] + 4, v4, v5, v6, v7) || different; different = bindingUpdated4(viewData[BINDING_INDEX] + 4, v4, v5, v6, v7) || different;
viewData[BINDING_INDEX] += 8; viewData[BINDING_INDEX] += 8;
@ -753,7 +754,7 @@ export function i18nInterpolation8(
*/ */
export function i18nInterpolationV(instructions: I18nExpInstruction[], values: any[]): string| export function i18nInterpolationV(instructions: I18nExpInstruction[], values: any[]): string|
NO_CHANGE { NO_CHANGE {
const viewData = _getViewData(); const viewData = getViewData();
let different = false; let different = false;
for (let i = 0; i < values.length; i++) { for (let i = 0; i < values.length; i++) {
// Check if bindings have changed // Check if bindings have changed

View File

@ -9,11 +9,11 @@ import {LifecycleHooksFeature, getHostElement, getRenderedText, renderComponent,
import {defineBase, defineComponent, defineDirective, defineNgModule, definePipe} from './definition'; import {defineBase, defineComponent, defineDirective, defineNgModule, definePipe} from './definition';
import {InheritDefinitionFeature} from './features/inherit_definition_feature'; import {InheritDefinitionFeature} from './features/inherit_definition_feature';
import {NgOnChangesFeature} from './features/ng_onchanges_feature'; import {NgOnChangesFeature} from './features/ng_onchanges_feature';
import {PublicFeature} from './features/public_feature'; import {ProvidersFeature} from './features/providers_feature';
import {BaseDef, ComponentDef, ComponentDefWithMeta, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveDefWithMeta, DirectiveType, PipeDef, PipeDefWithMeta} from './interfaces/definition'; import {BaseDef, ComponentDef, ComponentDefWithMeta, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveDefWithMeta, DirectiveType, PipeDef, PipeDefWithMeta} from './interfaces/definition';
export {ComponentFactory, ComponentFactoryResolver, ComponentRef, WRAP_RENDERER_FACTORY2, injectComponentFactoryResolver} from './component_ref'; export {ComponentFactory, ComponentFactoryResolver, ComponentRef, WRAP_RENDERER_FACTORY2, injectComponentFactoryResolver} from './component_ref';
export {directiveInject, getFactoryOf, getInheritedFactory, injectAttribute} from './di'; export {getFactoryOf, getInheritedFactory} from './di';
export {RenderFlags} from './interfaces/definition'; export {RenderFlags} from './interfaces/definition';
export {CssSelectorList} from './interfaces/projection'; export {CssSelectorList} from './interfaces/projection';
@ -51,9 +51,6 @@ export {
elementStyleProp, elementStyleProp,
elementStylingApply, elementStylingApply,
getCurrentView,
restoreView,
listener, listener,
store, store,
load, load,
@ -62,9 +59,6 @@ export {
namespaceMathML, namespaceMathML,
namespaceSVG, namespaceSVG,
enableBindings,
disableBindings,
projection, projection,
projectionDef, projectionDef,
@ -79,8 +73,19 @@ export {
detectChanges, detectChanges,
markDirty, markDirty,
tick, tick,
directiveInject,
injectAttribute,
} from './instructions'; } from './instructions';
export {
getCurrentView,
restoreView,
enableBindings,
disableBindings,
} from './state';
export { export {
i18nAttribute, i18nAttribute,
i18nExp, i18nExp,
@ -157,7 +162,7 @@ export {
DirectiveType, DirectiveType,
NgOnChangesFeature, NgOnChangesFeature,
InheritDefinitionFeature, InheritDefinitionFeature,
PublicFeature, ProvidersFeature,
PipeDef, PipeDef,
PipeDefWithMeta, PipeDefWithMeta,
LifecycleHooksFeature, LifecycleHooksFeature,

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Provider, ViewEncapsulation} from '../../core'; import {ViewEncapsulation} from '../../core';
import {Type} from '../../type'; import {Type} from '../../type';
import {CssSelectorList} from './projection'; import {CssSelectorList} from './projection';
@ -112,11 +112,11 @@ export interface DirectiveDef<T> extends BaseDef<T> {
/** Token representing the directive. Used by DI. */ /** Token representing the directive. Used by DI. */
type: Type<T>; type: Type<T>;
/** Function that makes a directive public to the DI system. */ /** Function that resolves providers and publishes them into the DI system. */
diPublic: ((def: DirectiveDef<T>) => void)|null; providersResolver: ((def: DirectiveDef<T>) => void)|null;
/** The selectors that will be used to match nodes to this directive. */ /** The selectors that will be used to match nodes to this directive. */
selectors: CssSelectorList; readonly selectors: CssSelectorList;
/** /**
* Name under which the directive is exported (for use with local references in template) * Name under which the directive is exported (for use with local references in template)
@ -126,12 +126,12 @@ export interface DirectiveDef<T> extends BaseDef<T> {
/** /**
* Factory function used to create a new directive instance. * Factory function used to create a new directive instance.
*/ */
factory(): T; factory: (t: Type<T>|null) => T;
/** /**
* Function to create instances of content queries associated with a given directive. * Function to create instances of content queries associated with a given directive.
*/ */
contentQueries: (() => void)|null; contentQueries: ((directiveIndex: number) => void)|null;
/** Refreshes content queries associated with directives in a given view */ /** Refreshes content queries associated with directives in a given view */
contentQueriesRefresh: ((directiveIndex: number, queryIndex: number) => void)|null; contentQueriesRefresh: ((directiveIndex: number, queryIndex: number) => void)|null;
@ -142,7 +142,7 @@ export interface DirectiveDef<T> extends BaseDef<T> {
* Used to calculate the length of the LViewData array for the *parent* component * Used to calculate the length of the LViewData array for the *parent* component
* of this directive/component. * of this directive/component.
*/ */
hostVars: number; readonly hostVars: number;
/** Refreshes host bindings on the associated directive. */ /** Refreshes host bindings on the associated directive. */
hostBindings: HostBindingsFunction|null; hostBindings: HostBindingsFunction|null;
@ -153,7 +153,7 @@ export interface DirectiveDef<T> extends BaseDef<T> {
* Even indices: attribute name * Even indices: attribute name
* Odd indices: attribute value * Odd indices: attribute value
*/ */
attributes: string[]|null; readonly attributes: string[]|null;
/* The following are lifecycle hooks for this component */ /* The following are lifecycle hooks for this component */
onInit: (() => void)|null; onInit: (() => void)|null;
@ -167,7 +167,7 @@ export interface DirectiveDef<T> extends BaseDef<T> {
/** /**
* The features applied to this directive * The features applied to this directive
*/ */
features: DirectiveDefFeature[]|null; readonly features: DirectiveDefFeature[]|null;
} }
export type ComponentDefWithMeta< export type ComponentDefWithMeta<
@ -245,18 +245,7 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
readonly onPush: boolean; readonly onPush: boolean;
/** /**
* Defines the set of injectable providers that are visible to a Directive and its content DOM
* children.
*/
readonly providers: Provider[]|null;
/**
* Defines the set of injectable providers that are visible to a Directive and its view DOM
* children only.
*/
readonly viewProviders: Provider[]|null;
/**
* Registry of directives and components that may be found in this view. * Registry of directives and components that may be found in this view.
* *
* The property is either an array of `DirectiveDef`s or a function which returns the array of * The property is either an array of `DirectiveDef`s or a function which returns the array of
@ -297,12 +286,12 @@ export interface PipeDef<T> {
* *
* Used to resolve pipe in templates. * Used to resolve pipe in templates.
*/ */
name: string; readonly name: string;
/** /**
* Factory function used to create a new pipe instance. * Factory function used to create a new pipe instance.
*/ */
factory: () => T; factory: (t: Type<T>|null) => T;
/** /**
* Whether or not the pipe is pure. * Whether or not the pipe is pure.
@ -310,7 +299,7 @@ export interface PipeDef<T> {
* Pure pipes result only depends on the pipe input and not on internal * Pure pipes result only depends on the pipe input and not on internal
* state of the pipe. * state of the pipe.
*/ */
pure: boolean; readonly pure: boolean;
/* The following are lifecycle hooks for this pipe */ /* The following are lifecycle hooks for this pipe */
onDestroy: (() => void)|null; onDestroy: (() => void)|null;

View File

@ -6,18 +6,32 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {InjectionToken} from '../../di/injection_token';
import {TContainerNode, TElementContainerNode, TElementNode,} from './node'; import {InjectFlags} from '../../di/injector';
import {Type} from '../../type';
import {TElementNode} from './node';
import {LViewData, TData} from './view';
export const TNODE = 8; export const TNODE = 8;
export const PARENT_INJECTOR = 8; export const PARENT_INJECTOR = 8;
export const INJECTOR_SIZE = 9; export const INJECTOR_SIZE = 9;
export const enum InjectorLocationFlags { /**
* Represents a relative location of parent injector.
*
* The interfaces encodes number of parents `LViewData`s to traverse and index in the `LViewData`
* pointing to the parent injector.
*/
export interface RelativeInjectorLocation { __brand__: 'RelativeInjectorLocationFlags'; }
export const enum RelativeInjectorLocationFlags {
InjectorIndexMask = 0b111111111111111, InjectorIndexMask = 0b111111111111111,
ViewOffsetShift = 15 ViewOffsetShift = 15,
NO_PARENT = -1,
} }
export const NO_PARENT_INJECTOR: RelativeInjectorLocation = -1 as any;
/** /**
* Each injector is saved in 9 contiguous slots in `LViewData` and 9 contiguous slots in * Each injector is saved in 9 contiguous slots in `LViewData` and 9 contiguous slots in
* `TView.data`. This allows us to store information about the current node's tokens (which * `TView.data`. This allows us to store information about the current node's tokens (which
@ -98,6 +112,140 @@ export const enum InjectorLocationFlags {
* } * }
*/ */
/**
* Factory for creating instances of injectors in the NodeInjector.
*
* This factory is complicated by the fact that it can resolve `multi` factories as well.
*
* NOTE: Some of the fields are optional which means that this class has two hidden classes.
* - One without `multi` support (most common)
* - One with `multi` values, (rare).
*
* Since VMs can cache up to 4 inline hidden classes this is OK.
*
* - Single factory: Only `resolving` and `factory` is defined.
* - `providers` factory: `componentProviders` is a number and `index = -1`.
* - `viewProviders` factory: `componentProviders` is a number and `index` points to `providers`.
*/
export class NodeInjectorFactory {
/**
* The inject implementation to be activated when using the factory.
*/
injectImpl: null|(<T>(token: Type<T>|InjectionToken<T>, flags: InjectFlags) => T);
/**
* Marker set to true during factory invocation to see if we get into recursive loop.
* Recursive loop causes an error to be displayed.
*/
resolving = false;
/**
* Marks that the token can see other Tokens declared in `viewProviders` on the same node.
*/
canSeeViewProviders: boolean;
/**
* An array of factories to use in case of `multi` provider.
*/
multi?: Array<() => any>;
/**
* Number of `multi`-providers which belong to the component.
*
* This is needed because when multiple components and directives declare the `multi` provider
* they have to be concatenated in the correct order.
*
* Example:
*
* If we have a component and directive active an a single element as declared here
* ```
* component:
* provides: [ {provide: String, useValue: 'component', multi: true} ],
* viewProvides: [ {provide: String, useValue: 'componentView', multi: true} ],
*
* directive:
* provides: [ {provide: String, useValue: 'directive', multi: true} ],
* ```
*
* Then the expected results are:
*
* ```
* providers: ['component', 'directive']
* viewProviders: ['component', 'componentView', 'directive']
* ```
*
* The way to think about it is that the `viewProviders` have been inserted after the component
* but before the directives, which is why we need to know how many `multi`s have been declared by
* the component.
*/
componentProviders?: number;
/**
* Current index of the Factory in the `data`. Needed for `viewProviders` and `providers` merging.
* See `providerFactory`.
*/
index?: number;
/**
* Because the same `multi` provider can be declared in `provides` and `viewProvides` it is
* possible for `viewProvides` to shadow the `provides`. For this reason we store the
* `provideFactory` of the `providers` so that `providers` can be extended with `viewProviders`.
*
* Example:
*
* Given:
* ```
* provides: [ {provide: String, useValue: 'all', multi: true} ],
* viewProvides: [ {provide: String, useValue: 'viewOnly', multi: true} ],
* ```
*
* We have to return `['all']` in case of content injection, but `['all', 'viewOnly']` in case
* of view injection. We further have to make sure that the shared instances (in our case
* `all`) are the exact same instance in both the content as well as the view injection. (We
* have to make sure that we don't double instantiate.) For this reason the `viewProvides`
* `Factory` has a pointer to the shadowed `provides` factory so that it can instantiate the
* `providers` (`['all']`) and then extend it with `viewProviders` (`['all'] + ['viewOnly'] =
* ['all', 'viewOnly']`).
*/
providerFactory?: NodeInjectorFactory|null;
constructor(
/**
* Factory to invoke in order to create a new instance.
*/
public factory:
(this: NodeInjectorFactory, _: null,
/**
* array where injectables tokens are stored. This is used in
* case of an error reporting to produce friendlier errors.
*/
tData: TData,
/**
* array where existing instances of injectables are stored. This is used in case
* of multi shadow is needed. See `multi` field documentation.
*/
lData: LViewData,
/**
* The TNode of the same element injector.
*/
tNode: TElementNode) => any,
/**
* Set to `true` if the token is declared in `viewProviders` (or if it is component).
*/
isViewProvider: boolean,
injectImplementation: null|(<T>(token: Type<T>|InjectionToken<T>, flags: InjectFlags) => T)) {
this.canSeeViewProviders = isViewProvider;
this.injectImpl = injectImplementation;
}
}
const FactoryPrototype = NodeInjectorFactory.prototype;
export function isFactory(obj: any): obj is NodeInjectorFactory {
// See: https://jsperf.com/instanceof-vs-getprototypeof
return obj != null && typeof obj == 'object' && Object.getPrototypeOf(obj) == FactoryPrototype;
}
// Note: This hack is necessary so we don't erroneously get a circular dependency // Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types. // failure based on types.
export const unusedValueExportToPlacateAjd = 1; export const unusedValueExportToPlacateAjd = 1;

View File

@ -46,6 +46,18 @@ export const enum TNodeFlags {
DirectiveStartingIndexShift = 16, DirectiveStartingIndexShift = 16,
} }
/**
* Corresponds to the TNode.providerIndexes property.
*/
export const enum TNodeProviderIndexes {
/** The index of the first provider on this node is encoded on the least significant bits */
ProvidersStartIndexMask = 0b00000000000000001111111111111111,
/** The count of view providers from the component on this node is encoded on the 16 most
significant bits */
CptViewProvidersCountShift = 16,
CptViewProvidersCountShifter = 0b00000000000000010000000000000000,
}
/** /**
* A set of marker values to be used in the attributes arrays. Those markers indicate that some * A set of marker values to be used in the attributes arrays. Those markers indicate that some
* items are not regular attributes and the processing should be adapted accordingly. * items are not regular attributes and the processing should be adapted accordingly.
@ -125,6 +137,14 @@ export interface TNode {
*/ */
flags: TNodeFlags; flags: TNodeFlags;
/**
* This number stores two values using its bits:
*
* - the index of the first provider on that node (first 16 bits)
* - the count of view providers from the component on this node (last 16 bits)
*/
providerIndexes: TNodeProviderIndexes;
/** The tag name associated with this node. */ /** The tag name associated with this node. */
tagName: string|null; tagName: string|null;

View File

@ -6,9 +6,11 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {InjectionToken} from '../../di/injection_token';
import {Injector} from '../../di/injector'; import {Injector} from '../../di/injector';
import {QueryList} from '../../linker'; import {QueryList} from '../../linker';
import {Sanitizer} from '../../sanitization/security'; import {Sanitizer} from '../../sanitization/security';
import {Type} from '../../type';
import {LContainer} from './container'; import {LContainer} from './container';
import {ComponentDef, ComponentQuery, ComponentTemplate, DirectiveDef, DirectiveDefList, HostBindingsFunction, PipeDef, PipeDefList} from './definition'; import {ComponentDef, ComponentQuery, ComponentTemplate, DirectiveDef, DirectiveDefList, HostBindingsFunction, PipeDef, PipeDefList} from './definition';
@ -335,24 +337,6 @@ export interface TView {
*/ */
firstChild: TNode|null; firstChild: TNode|null;
/**
* Selector matches for a node are temporarily cached on the TView so the
* DI system can eagerly instantiate directives on the same node if they are
* created out of order. They are overwritten after each node.
*
* <div dirA dirB></div>
*
* e.g. DirA injects DirB, but DirA is created first. DI should instantiate
* DirB when it finds that it's on the same node, but not yet created.
*
* Even indices: Directive defs
* Odd indices:
* - Null if the associated directive hasn't been instantiated yet
* - Directive index, if associated directive has been created
* - String, temporary 'CIRCULAR' token set while dependencies are being resolved
*/
currentMatches: CurrentMatchesList|null;
/** /**
* Set of instructions used to process host bindings efficiently. * Set of instructions used to process host bindings efficiently.
* *
@ -549,10 +533,9 @@ export type HookData = (number | (() => void))[];
* *
* Injector bloom filters are also stored here. * Injector bloom filters are also stored here.
*/ */
export type TData = (TNode | PipeDef<any>| DirectiveDef<any>| ComponentDef<any>| number | null)[]; export type TData =
(TNode | PipeDef<any>| DirectiveDef<any>| ComponentDef<any>| number | Type<any>|
/** Type for TView.currentMatches */ InjectionToken<any>| null)[];
export type CurrentMatchesList = [DirectiveDef<any>, (string | number | null)];
// Note: This hack is necessary so we don't erroneously get a circular dependency // Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types. // failure based on types.

View File

@ -80,6 +80,8 @@ export function compileComponent(type: Type<any>, metadata: Component): void {
wrapDirectivesInClosure: false, wrapDirectivesInClosure: false,
styles: metadata.styles || [], styles: metadata.styles || [],
encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated, animations, encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated, animations,
viewProviders: metadata.viewProviders ? new WrappedNodeExpr(metadata.viewProviders) :
null
}, },
constantPool, makeBindingParser()); constantPool, makeBindingParser());
const preStatements = [...constantPool.statements, ...res.statements]; const preStatements = [...constantPool.statements, ...res.statements];
@ -180,6 +182,7 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
typeSourceSpan: null !, typeSourceSpan: null !,
usesInheritance: !extendsDirectlyFromObject(type), usesInheritance: !extendsDirectlyFromObject(type),
exportAs: metadata.exportAs || null, exportAs: metadata.exportAs || null,
providers: metadata.providers ? new WrappedNodeExpr(metadata.providers) : null
}; };
} }

View File

@ -32,7 +32,7 @@ export const angularCoreEnv: {[name: string]: Function} = {
'ɵinjectAttribute': r3.injectAttribute, 'ɵinjectAttribute': r3.injectAttribute,
'ɵtemplateRefExtractor': r3.templateRefExtractor, 'ɵtemplateRefExtractor': r3.templateRefExtractor,
'ɵNgOnChangesFeature': r3.NgOnChangesFeature, 'ɵNgOnChangesFeature': r3.NgOnChangesFeature,
'ɵPublicFeature': r3.PublicFeature, 'ɵProvidersFeature': r3.ProvidersFeature,
'ɵInheritDefinitionFeature': r3.InheritDefinitionFeature, 'ɵInheritDefinitionFeature': r3.InheritDefinitionFeature,
'ɵelementAttribute': r3.elementAttribute, 'ɵelementAttribute': r3.elementAttribute,
'ɵbind': r3.bind, 'ɵbind': r3.bind,

View File

@ -8,10 +8,11 @@
import {PipeTransform} from '../change_detection/pipe_transform'; import {PipeTransform} from '../change_detection/pipe_transform';
import {getTView, load, store} from './instructions'; import {load, store} from './instructions';
import {PipeDef, PipeDefList} from './interfaces/definition'; import {PipeDef, PipeDefList} from './interfaces/definition';
import {HEADER_OFFSET} from './interfaces/view'; import {HEADER_OFFSET} from './interfaces/view';
import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunctionV} from './pure_function'; import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunctionV} from './pure_function';
import {getTView} from './state';
/** /**
* Create a pipe. * Create a pipe.
@ -36,7 +37,7 @@ export function pipe(index: number, pipeName: string): any {
pipeDef = tView.data[adjustedIndex] as PipeDef<any>; pipeDef = tView.data[adjustedIndex] as PipeDef<any>;
} }
const pipeInstance = pipeDef.factory(); const pipeInstance = pipeDef.factory(null);
store(index, pipeInstance); store(index, pipeInstance);
return pipeInstance; return pipeInstance;
} }

View File

@ -6,7 +6,9 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {bindingUpdated, bindingUpdated2, bindingUpdated4, updateBinding, getBinding, getCreationMode, bindingUpdated3, getBindingRoot, getTView,} from './instructions'; import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4, getBinding, updateBinding} from './instructions';
import {getBindingRoot, getCreationMode} from './state';
/** /**
* Bindings for pure functions are stored after regular bindings. * Bindings for pure functions are stored after regular bindings.

View File

@ -19,12 +19,13 @@ import {getSymbolIterator} from '../util';
import {assertDefined, assertEqual} from './assert'; import {assertDefined, assertEqual} from './assert';
import {NG_ELEMENT_ID} from './fields'; import {NG_ELEMENT_ID} from './fields';
import {_getViewData, assertPreviousIsParent, getOrCreateCurrentQueries, store, storeCleanupWithContext} from './instructions'; import {store, storeCleanupWithContext} from './instructions';
import {DirectiveDef, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition'; import {DirectiveDef, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition';
import {unusedValueExportToPlacateAjd as unused2} from './interfaces/injector'; import {unusedValueExportToPlacateAjd as unused2} from './interfaces/injector';
import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, unusedValueExportToPlacateAjd as unused3} from './interfaces/node'; import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, unusedValueExportToPlacateAjd as unused3} from './interfaces/node';
import {LQueries, unusedValueExportToPlacateAjd as unused4} from './interfaces/query'; import {LQueries, unusedValueExportToPlacateAjd as unused4} from './interfaces/query';
import {LViewData, TVIEW} from './interfaces/view'; import {LViewData, TVIEW} from './interfaces/view';
import {assertPreviousIsParent, getOrCreateCurrentQueries, getViewData} from './state';
import {flatten, isContentQueryHost} from './util'; import {flatten, isContentQueryHost} from './util';
import {createElementRef, createTemplateRef} from './view_engine_compatibility'; import {createElementRef, createTemplateRef} from './view_engine_compatibility';
@ -259,7 +260,7 @@ function getIdxOfMatchingDirective(tNode: TNode, currentView: LViewData, type: T
const end = start + count; const end = start + count;
for (let i = start; i < end; i++) { for (let i = start; i < end; i++) {
const def = defs[i] as DirectiveDef<any>; const def = defs[i] as DirectiveDef<any>;
if (def.type === type && def.diPublic) { if (def.type === type) {
return i; return i;
} }
} }
@ -293,7 +294,7 @@ function queryReadByTNodeType(tNode: TNode, currentView: LViewData): any {
function add( function add(
query: LQuery<any>| null, tNode: TElementNode | TContainerNode | TElementContainerNode) { query: LQuery<any>| null, tNode: TElementNode | TContainerNode | TElementContainerNode) {
const currentView = _getViewData(); const currentView = getViewData();
while (query) { while (query) {
const predicate = query.predicate; const predicate = query.predicate;

View File

@ -0,0 +1,432 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* 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 {Sanitizer} from '../sanitization/security';
import {assertDefined, assertEqual} from './assert';
import {executeHooks} from './hooks';
import {TElementNode, TNode, TNodeFlags, TViewNode} from './interfaces/node';
import {LQueries} from './interfaces/query';
import {Renderer3, RendererFactory3} from './interfaces/renderer';
import {BINDING_INDEX, CLEANUP, CONTEXT, DECLARATION_VIEW, FLAGS, HOST_NODE, LViewData, LViewFlags, OpaqueViewState, QUERIES, RENDERER, SANITIZER, TVIEW, TView} from './interfaces/view';
import {assertDataInRangeInternal, isContentQueryHost} from './util';
/**
* This property gets set before entering a template.
*
* This renderer can be one of two varieties of Renderer3:
*
* - ObjectedOrientedRenderer3
*
* This is the native browser API style, e.g. operations are methods on individual objects
* like HTMLElement. With this style, no additional code is needed as a facade (reducing payload
* size).
*
* - ProceduralRenderer3
*
* In non-native browser environments (e.g. platforms such as web-workers), this is the facade
* that enables element manipulation. This also facilitates backwards compatibility with
* Renderer2.
*/
let renderer: Renderer3;
export function getRenderer(): Renderer3 {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return renderer;
}
export function setRenderer(r: Renderer3): void {
renderer = r;
}
let rendererFactory: RendererFactory3;
export function getRendererFactory(): RendererFactory3 {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return rendererFactory;
}
export function setRendererFactory(factory: RendererFactory3): void {
rendererFactory = factory;
}
export function getCurrentSanitizer(): Sanitizer|null {
return viewData && viewData[SANITIZER];
}
/**
* Store the element depth count. This is used to identify the root elements of the template
* so that we can than attach `LViewData` to only those elements.
*/
let elementDepthCount !: number;
export function getElementDepthCount() {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return elementDepthCount;
}
export function increaseElementDepthCount() {
elementDepthCount++;
}
export function decreaseElementDepthCount() {
elementDepthCount--;
}
/**
* Stores whether directives should be matched to elements.
*
* When template contains `ngNonBindable` than we need to prevent the runtime form matching
* directives on children of that element.
*
* Example:
* ```
* <my-comp my-directive>
* Should match component / directive.
* </my-comp>
* <div ngNonBindable>
* <my-comp my-directive>
* Should not match component / directive because we are in ngNonBindable.
* </my-comp>
* </div>
* ```
*/
let bindingsEnabled !: boolean;
export function getBindingsEnabled(): boolean {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return bindingsEnabled;
}
/**
* Enables directive matching on elements.
*
* * Example:
* ```
* <my-comp my-directive>
* Should match component / directive.
* </my-comp>
* <div ngNonBindable>
* <!-- disabledBindings() -->
* <my-comp my-directive>
* Should not match component / directive because we are in ngNonBindable.
* </my-comp>
* <!-- enableBindings() -->
* </div>
* ```
*/
export function enableBindings(): void {
bindingsEnabled = true;
}
/**
* Disables directive matching on element.
*
* * Example:
* ```
* <my-comp my-directive>
* Should match component / directive.
* </my-comp>
* <div ngNonBindable>
* <!-- disabledBindings() -->
* <my-comp my-directive>
* Should not match component / directive because we are in ngNonBindable.
* </my-comp>
* <!-- enableBindings() -->
* </div>
* ```
*/
export function disableBindings(): void {
bindingsEnabled = false;
}
/**
* Returns the current OpaqueViewState instance.
*
* Used in conjunction with the restoreView() instruction to save a snapshot
* of the current view and restore it when listeners are invoked. This allows
* walking the declaration view tree in listeners to get vars from parent views.
*/
export function getCurrentView(): OpaqueViewState {
return viewData as any as OpaqueViewState;
}
/**
* Restores `contextViewData` to the given OpaqueViewState instance.
*
* Used in conjunction with the getCurrentView() instruction to save a snapshot
* of the current view and restore it when listeners are invoked. This allows
* walking the declaration view tree in listeners to get vars from parent views.
*
* @param viewToRestore The OpaqueViewState instance to restore.
*/
export function restoreView(viewToRestore: OpaqueViewState) {
contextViewData = viewToRestore as any as LViewData;
}
/** Used to set the parent property when nodes are created and track query results. */
let previousOrParentTNode: TNode;
export function getPreviousOrParentTNode(): TNode {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return previousOrParentTNode;
}
export function setPreviousOrParentTNode(tNode: TNode) {
previousOrParentTNode = tNode;
}
export function setTNodeAndViewData(tNode: TNode, view: LViewData) {
previousOrParentTNode = tNode;
viewData = view;
}
/**
* If `isParent` is:
* - `true`: then `previousOrParentTNode` points to a parent node.
* - `false`: then `previousOrParentTNode` points to previous node (sibling).
*/
let isParent: boolean;
export function getIsParent(): boolean {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return isParent;
}
export function setIsParent(value: boolean): void {
isParent = value;
}
let tView: TView;
export function getTView(): TView {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return tView;
}
let currentQueries: LQueries|null;
export function getCurrentQueries(): LQueries|null {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return currentQueries;
}
export function setCurrentQueries(queries: LQueries | null): void {
currentQueries = queries;
}
/**
* Query instructions can ask for "current queries" in 2 different cases:
* - when creating view queries (at the root of a component view, before any node is created - in
* this case currentQueries points to view queries)
* - when creating content queries (i.e. this previousOrParentTNode points to a node on which we
* create content queries).
*/
export function getOrCreateCurrentQueries(
QueryType: {new (parent: null, shallow: null, deep: null): LQueries}): LQueries {
// if this is the first content query on a node, any existing LQueries needs to be cloned
// in subsequent template passes, the cloning occurs before directive instantiation.
if (previousOrParentTNode && previousOrParentTNode !== viewData[HOST_NODE] &&
!isContentQueryHost(previousOrParentTNode)) {
currentQueries && (currentQueries = currentQueries.clone());
previousOrParentTNode.flags |= TNodeFlags.hasContentQuery;
}
return currentQueries || (currentQueries = new QueryType(null, null, null));
}
/**
* This property gets set before entering a template.
*/
let creationMode: boolean;
export function getCreationMode(): boolean {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return creationMode;
}
/**
* State of the current view being processed.
*
* An array of nodes (text, element, container, etc), pipes, their bindings, and
* any local variables that need to be stored between invocations.
*/
let viewData: LViewData;
/**
* Internal function that returns the current LViewData instance.
*
* The getCurrentView() instruction should be used for anything public.
*/
export function getViewData(): LViewData {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return viewData;
}
/**
* The last viewData retrieved by nextContext().
* Allows building nextContext() and reference() calls.
*
* e.g. const inner = x().$implicit; const outer = x().$implicit;
*/
let contextViewData: LViewData = null !;
export function getContextViewData(): LViewData {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return contextViewData;
}
export function getCleanup(view: LViewData): any[] {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return view[CLEANUP] || (view[CLEANUP] = []);
}
export function getTViewCleanup(view: LViewData): any[] {
return view[TVIEW].cleanup || (view[TVIEW].cleanup = []);
}
/**
* In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error.
*
* Necessary to support ChangeDetectorRef.checkNoChanges().
*/
let checkNoChangesMode = false;
export function getCheckNoChangesMode(): boolean {
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
return checkNoChangesMode;
}
export function setCheckNoChangesMode(mode: boolean): void {
checkNoChangesMode = mode;
}
/** Whether or not this is the first time the current view has been processed. */
let firstTemplatePass = true;
export function getFirstTemplatePass(): boolean {
return firstTemplatePass;
}
export function setFirstTemplatePass(value: boolean): void {
firstTemplatePass = value;
}
/**
* The root index from which pure function instructions should calculate their binding
* indices. In component views, this is TView.bindingStartIndex. In a host binding
* context, this is the TView.expandoStartIndex + any dirs/hostVars before the given dir.
*/
let bindingRootIndex: number = -1;
// top level variables should not be exported for performance reasons (PERF_NOTES.md)
export function getBindingRoot() {
return bindingRootIndex;
}
export function setBindingRoot(value: number) {
bindingRootIndex = value;
}
/**
* Swap the current state with a new state.
*
* For performance reasons we store the state in the top level of the module.
* This way we minimize the number of properties to read. Whenever a new view
* is entered we have to store the state for later, and when the view is
* exited the state has to be restored
*
* @param newView New state to become active
* @param host Element to which the View is a child of
* @returns the previous state;
*/
export function enterView(
newView: LViewData, hostTNode: TElementNode | TViewNode | null): LViewData {
const oldView: LViewData = viewData;
tView = newView && newView[TVIEW];
creationMode = newView && (newView[FLAGS] & LViewFlags.CreationMode) === LViewFlags.CreationMode;
firstTemplatePass = newView && tView.firstTemplatePass;
bindingRootIndex = newView && tView.bindingStartIndex;
renderer = newView && newView[RENDERER];
previousOrParentTNode = hostTNode !;
isParent = true;
viewData = contextViewData = newView;
oldView && (oldView[QUERIES] = currentQueries);
currentQueries = newView && newView[QUERIES];
return oldView;
}
export function nextContextImpl<T = any>(level: number = 1): T {
contextViewData = walkUpViews(level, contextViewData !);
return contextViewData[CONTEXT] as T;
}
function walkUpViews(nestingLevel: number, currentView: LViewData): LViewData {
while (nestingLevel > 0) {
ngDevMode && assertDefined(
currentView[DECLARATION_VIEW],
'Declaration view should be defined if nesting level is greater than 0.');
currentView = currentView[DECLARATION_VIEW] !;
nestingLevel--;
}
return currentView;
}
/**
* Resets the application state.
*/
export function resetComponentState() {
isParent = false;
previousOrParentTNode = null !;
elementDepthCount = 0;
bindingsEnabled = true;
}
/**
* Used in lieu of enterView to make it clear when we are exiting a child view. This makes
* the direction of traversal (up or down the view tree) a bit clearer.
*
* @param newView New state to become active
* @param creationOnly An optional boolean to indicate that the view was processed in creation mode
* only, i.e. the first update will be done later. Only possible for dynamically created views.
*/
export function leaveView(newView: LViewData, creationOnly?: boolean): void {
if (!creationOnly) {
if (!checkNoChangesMode) {
executeHooks(viewData, tView.viewHooks, tView.viewCheckHooks, creationMode);
}
// Views are clean and in update mode after being checked, so these bits are cleared
viewData[FLAGS] &= ~(LViewFlags.CreationMode | LViewFlags.Dirty);
}
viewData[FLAGS] |= LViewFlags.RunInit;
viewData[BINDING_INDEX] = tView.bindingStartIndex;
enterView(newView, null);
}
export function assertPreviousIsParent() {
assertEqual(isParent, true, 'previousOrParentTNode should be a parent');
}
export function assertHasParent() {
assertDefined(previousOrParentTNode.parent, 'previousOrParentTNode should have a parent');
}
export function assertDataInRange(index: number, arr?: any[]) {
if (arr == null) arr = viewData;
assertDataInRangeInternal(index, arr || viewData);
}
export function assertDataNext(index: number, arr?: any[]) {
if (arr == null) arr = viewData;
assertEqual(
arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
}

View File

@ -11,10 +11,13 @@ import {devModeEqual} from '../change_detection/change_detection_util';
import {assertDefined, assertLessThan} from './assert'; import {assertDefined, assertLessThan} from './assert';
import {ACTIVE_INDEX, LContainer} from './interfaces/container'; import {ACTIVE_INDEX, LContainer} from './interfaces/container';
import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context'; import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context';
import {TNode, TNodeFlags} from './interfaces/node'; import {ComponentDef, DirectiveDef} from './interfaces/definition';
import {NO_PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags} from './interfaces/injector';
import {TContainerNode, TElementNode, TNode, TNodeFlags} from './interfaces/node';
import {RComment, RElement, RText} from './interfaces/renderer'; import {RComment, RElement, RText} from './interfaces/renderer';
import {StylingContext} from './interfaces/styling'; import {StylingContext} from './interfaces/styling';
import {CONTEXT, FLAGS, HEADER_OFFSET, HOST, LViewData, LViewFlags, PARENT, RootContext, TData, TVIEW} from './interfaces/view'; import {CONTEXT, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, HOST_NODE, LViewData, LViewFlags, PARENT, RootContext, TData, TVIEW} from './interfaces/view';
/** /**
@ -122,6 +125,10 @@ export function isComponent(tNode: TNode): boolean {
return (tNode.flags & TNodeFlags.isComponent) === TNodeFlags.isComponent; return (tNode.flags & TNodeFlags.isComponent) === TNodeFlags.isComponent;
} }
export function isComponentDef<T>(def: DirectiveDef<T>): def is ComponentDef<T> {
return (def as ComponentDef<T>).template !== null;
}
export function isLContainer(value: RElement | RComment | LContainer | StylingContext): boolean { export function isLContainer(value: RElement | RComment | LContainer | StylingContext): boolean {
// Styling contexts are also arrays, but their first index contains an element node // Styling contexts are also arrays, but their first index contains an element node
return Array.isArray(value) && typeof value[ACTIVE_INDEX] === 'number'; return Array.isArray(value) && typeof value[ACTIVE_INDEX] === 'number';
@ -161,3 +168,72 @@ export function readPatchedLViewData(target: any): LViewData|null {
} }
return null; return null;
} }
export function hasParentInjector(parentLocation: RelativeInjectorLocation): boolean {
return parentLocation !== NO_PARENT_INJECTOR;
}
export function getParentInjectorIndex(parentLocation: RelativeInjectorLocation): number {
return (parentLocation as any as number) & RelativeInjectorLocationFlags.InjectorIndexMask;
}
export function getParentInjectorViewOffset(parentLocation: RelativeInjectorLocation): number {
return (parentLocation as any as number) >> RelativeInjectorLocationFlags.ViewOffsetShift;
}
/**
* Unwraps a parent injector location number to find the view offset from the current injector,
* then walks up the declaration view tree until the view is found that contains the parent
* injector.
*
* @param location The location of the parent injector, which contains the view offset
* @param startView The LViewData instance from which to start walking up the view tree
* @returns The LViewData instance that contains the parent injector
*/
export function getParentInjectorView(
location: RelativeInjectorLocation, startView: LViewData): LViewData {
let viewOffset = getParentInjectorViewOffset(location);
let parentView = startView;
// For most cases, the parent injector can be found on the host node (e.g. for component
// or container), but we must keep the loop here to support the rarer case of deeply nested
// <ng-template> tags or inline views, where the parent injector might live many views
// above the child injector.
while (viewOffset > 0) {
parentView = parentView[DECLARATION_VIEW] !;
viewOffset--;
}
return parentView;
}
/**
* Unwraps a parent injector location number to find the view offset from the current injector,
* then walks up the declaration view tree until the TNode of the parent injector is found.
*
* @param location The location of the parent injector, which contains the view offset
* @param startView The LViewData instance from which to start walking up the view tree
* @param startTNode The TNode instance of the starting element
* @returns The TNode of the parent injector
*/
export function getParentInjectorTNode(
location: RelativeInjectorLocation, startView: LViewData, startTNode: TNode): TElementNode|
TContainerNode|null {
if (startTNode.parent && startTNode.parent.injectorIndex !== -1) {
// view offset is 0
const injectorIndex = startTNode.parent.injectorIndex;
let parentTNode = startTNode.parent;
while (parentTNode.parent != null && injectorIndex == parentTNode.injectorIndex) {
parentTNode = parentTNode.parent;
}
return parentTNode;
}
let viewOffset = getParentInjectorViewOffset(location);
let parentView = startView;
let parentTNode = startView[HOST_NODE] as TElementNode;
while (viewOffset > 0) {
parentView = parentView[DECLARATION_VIEW] !;
parentTNode = parentView[HOST_NODE] as TElementNode;
viewOffset--;
}
return parentTNode;
}

View File

@ -17,18 +17,18 @@ import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_Vie
import {Renderer2} from '../render/api'; import {Renderer2} from '../render/api';
import {assertDefined, assertGreaterThan, assertLessThan} from './assert'; import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
import {NodeInjector, getParentInjectorLocation, getParentInjectorView} from './di'; import {getOrCreateInjectable, getParentInjectorLocation} from './di';
import {_getViewData, addToViewTree, createEmbeddedViewAndNode, createLContainer, getPreviousOrParentTNode, getRenderer, renderEmbeddedTemplate} from './instructions'; import {addToViewTree, createEmbeddedViewAndNode, createLContainer, renderEmbeddedTemplate} from './instructions';
import {ACTIVE_INDEX, LContainer, NATIVE, RENDER_PARENT, VIEWS} from './interfaces/container'; import {ACTIVE_INDEX, LContainer, NATIVE, VIEWS} from './interfaces/container';
import {RenderFlags} from './interfaces/definition'; import {RenderFlags} from './interfaces/definition';
import {InjectorLocationFlags} from './interfaces/injector';
import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode} from './interfaces/node'; import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode} from './interfaces/node';
import {LQueries} from './interfaces/query'; import {LQueries} from './interfaces/query';
import {RComment, RElement, Renderer3, isProceduralRenderer} from './interfaces/renderer'; import {RComment, RElement, Renderer3, isProceduralRenderer} from './interfaces/renderer';
import {CONTEXT, HOST_NODE, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view'; import {CONTEXT, HOST_NODE, LViewData, QUERIES, RENDERER, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert'; import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
import {addRemoveViewFromContainer, appendChild, detachView, findComponentView, getBeforeNodeForView, getRenderParent, insertView, removeView} from './node_manipulation'; import {addRemoveViewFromContainer, appendChild, detachView, findComponentView, getBeforeNodeForView, getRenderParent, insertView, removeView} from './node_manipulation';
import {getComponentViewByIndex, getNativeByTNode, isComponent, isLContainer} from './util'; import {getPreviousOrParentTNode, getRenderer, getViewData} from './state';
import {getComponentViewByIndex, getNativeByTNode, getParentInjectorTNode, getParentInjectorView, hasParentInjector, isComponent, isLContainer} from './util';
import {ViewRef} from './view_ref'; import {ViewRef} from './view_ref';
@ -40,7 +40,7 @@ import {ViewRef} from './view_ref';
*/ */
export function injectElementRef(ElementRefToken: typeof ViewEngine_ElementRef): export function injectElementRef(ElementRefToken: typeof ViewEngine_ElementRef):
ViewEngine_ElementRef { ViewEngine_ElementRef {
return createElementRef(ElementRefToken, getPreviousOrParentTNode(), _getViewData()); return createElementRef(ElementRefToken, getPreviousOrParentTNode(), getViewData());
} }
let R3ElementRef: {new (native: RElement | RComment): ViewEngine_ElementRef}; let R3ElementRef: {new (native: RElement | RComment): ViewEngine_ElementRef};
@ -79,7 +79,7 @@ export function injectTemplateRef<T>(
TemplateRefToken: typeof ViewEngine_TemplateRef, TemplateRefToken: typeof ViewEngine_TemplateRef,
ElementRefToken: typeof ViewEngine_ElementRef): ViewEngine_TemplateRef<T> { ElementRefToken: typeof ViewEngine_ElementRef): ViewEngine_TemplateRef<T> {
return createTemplateRef<T>( return createTemplateRef<T>(
TemplateRefToken, ElementRefToken, getPreviousOrParentTNode(), _getViewData()); TemplateRefToken, ElementRefToken, getPreviousOrParentTNode(), getViewData());
} }
/** /**
@ -147,9 +147,18 @@ export function injectViewContainerRef(
ElementRefToken: typeof ViewEngine_ElementRef): ViewEngine_ViewContainerRef { ElementRefToken: typeof ViewEngine_ElementRef): ViewEngine_ViewContainerRef {
const previousTNode = const previousTNode =
getPreviousOrParentTNode() as TElementNode | TElementContainerNode | TContainerNode; getPreviousOrParentTNode() as TElementNode | TElementContainerNode | TContainerNode;
return createContainerRef(ViewContainerRefToken, ElementRefToken, previousTNode, _getViewData()); return createContainerRef(ViewContainerRefToken, ElementRefToken, previousTNode, getViewData());
} }
export class NodeInjector implements Injector {
constructor(
private _tNode: TElementNode|TContainerNode|TElementContainerNode,
private _hostView: LViewData) {}
get(token: any, notFoundValue?: any): any {
return getOrCreateInjectable(this._tNode, this._hostView, token, notFoundValue);
}
}
/** /**
* Creates a ViewContainerRef and stores it on the injector. * Creates a ViewContainerRef and stores it on the injector.
@ -187,11 +196,11 @@ export function createContainerRef(
get parentInjector(): Injector { get parentInjector(): Injector {
const parentLocation = getParentInjectorLocation(this._hostTNode, this._hostView); const parentLocation = getParentInjectorLocation(this._hostTNode, this._hostView);
const parentView = getParentInjectorView(parentLocation, this._hostView); const parentView = getParentInjectorView(parentLocation, this._hostView);
const parentIndex = parentLocation & InjectorLocationFlags.InjectorIndexMask; const parentTNode = getParentInjectorTNode(parentLocation, this._hostView, this._hostTNode);
const parentTNode = parentView[TVIEW].data[parentIndex] as TElementNode | TContainerNode;
return parentLocation === -1 ? new NullInjector() : return !hasParentInjector(parentLocation) || parentTNode == null ?
new NodeInjector(parentTNode, parentView); new NullInjector() :
new NodeInjector(parentTNode, parentView);
} }
clear(): void { clear(): void {
@ -310,7 +319,7 @@ export function createContainerRef(
/** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */ /** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */
export function injectChangeDetectorRef(): ViewEngine_ChangeDetectorRef { export function injectChangeDetectorRef(): ViewEngine_ChangeDetectorRef {
return createViewRef(getPreviousOrParentTNode(), _getViewData(), null); return createViewRef(getPreviousOrParentTNode(), getViewData(), null);
} }
/** /**
@ -345,5 +354,5 @@ function getOrCreateRenderer2(view: LViewData): Renderer2 {
/** Returns a Renderer2 (or throws when application was bootstrapped with Renderer3) */ /** Returns a Renderer2 (or throws when application was bootstrapped with Renderer3) */
export function injectRenderer2(): Renderer2 { export function injectRenderer2(): Renderer2 {
return getOrCreateRenderer2(_getViewData()); return getOrCreateRenderer2(getViewData());
} }

View File

@ -11,10 +11,11 @@ import {ChangeDetectorRef as viewEngine_ChangeDetectorRef} from '../change_detec
import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_container_ref'; import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_container_ref';
import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, InternalViewRef as viewEngine_InternalViewRef} from '../linker/view_ref'; import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, InternalViewRef as viewEngine_InternalViewRef} from '../linker/view_ref';
import {checkNoChanges, checkNoChangesInRootView, detectChanges, detectChangesInRootView, getRendererFactory, markViewDirty, storeCleanupFn, viewAttached} from './instructions'; import {checkNoChanges, checkNoChangesInRootView, detectChanges, detectChangesInRootView, markViewDirty, storeCleanupFn, viewAttached} from './instructions';
import {TViewNode} from './interfaces/node'; import {TViewNode} from './interfaces/node';
import {FLAGS, LViewData, LViewFlags, PARENT} from './interfaces/view'; import {FLAGS, LViewData, LViewFlags, PARENT} from './interfaces/view';
import {destroyLView} from './node_manipulation'; import {destroyLView} from './node_manipulation';
import {getRendererFactory} from './state';
// Needed due to tsickle downleveling where multiple `implements` with classes creates // Needed due to tsickle downleveling where multiple `implements` with classes creates

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {getCurrentSanitizer} from '../render3/instructions'; import {getCurrentSanitizer} from '../render3/state';
import {stringify} from '../render3/util'; import {stringify} from '../render3/util';
import {BypassType, allowSanitizationBypass} from './bypass'; import {BypassType, allowSanitizationBypass} from './bypass';

View File

@ -17,9 +17,6 @@
{ {
"name": "BoundPlayerFactory" "name": "BoundPlayerFactory"
}, },
{
"name": "CIRCULAR$1"
},
{ {
"name": "CLEANUP" "name": "CLEANUP"
}, },
@ -71,6 +68,9 @@
{ {
"name": "FLAGS" "name": "FLAGS"
}, },
{
"name": "FactoryPrototype"
},
{ {
"name": "HEADER_OFFSET" "name": "HEADER_OFFSET"
}, },
@ -119,9 +119,15 @@
{ {
"name": "NG_PROJECT_AS_ATTR_NAME" "name": "NG_PROJECT_AS_ATTR_NAME"
}, },
{
"name": "NOT_FOUND"
},
{ {
"name": "NO_CHANGE" "name": "NO_CHANGE"
}, },
{
"name": "NO_PARENT_INJECTOR"
},
{ {
"name": "NgForOf" "name": "NgForOf"
}, },
@ -134,6 +140,9 @@
{ {
"name": "NodeInjector" "name": "NodeInjector"
}, },
{
"name": "NodeInjectorFactory"
},
{ {
"name": "NullInjector" "name": "NullInjector"
}, },
@ -152,9 +161,6 @@
{ {
"name": "PARENT_INJECTOR" "name": "PARENT_INJECTOR"
}, },
{
"name": "PublicFeature"
},
{ {
"name": "QUERIES" "name": "QUERIES"
}, },
@ -263,18 +269,12 @@
{ {
"name": "_c4" "name": "_c4"
}, },
{
"name": "_currentInjector"
},
{ {
"name": "_currentNamespace" "name": "_currentNamespace"
}, },
{ {
"name": "_devMode" "name": "_devMode"
}, },
{
"name": "_getViewData"
},
{ {
"name": "_global" "name": "_global"
}, },
@ -315,7 +315,7 @@
"name": "attachPatchData" "name": "attachPatchData"
}, },
{ {
"name": "baseDirectiveCreate" "name": "baseResolveDirective"
}, },
{ {
"name": "bind" "name": "bind"
@ -323,24 +323,21 @@
{ {
"name": "bindPlayerFactory" "name": "bindPlayerFactory"
}, },
{
"name": "bindingRootIndex"
},
{ {
"name": "bindingUpdated" "name": "bindingUpdated"
}, },
{ {
"name": "bloomAdd" "name": "bloomAdd"
}, },
{
"name": "bloomHasToken"
},
{ {
"name": "bloomHashBitOrFactory" "name": "bloomHashBitOrFactory"
}, },
{ {
"name": "buildAnimationPlayer" "name": "buildAnimationPlayer"
}, },
{
"name": "cacheMatchingDirectivesForNode"
},
{ {
"name": "cacheMatchingLocalNames" "name": "cacheMatchingLocalNames"
}, },
@ -437,6 +434,9 @@
{ {
"name": "createViewQuery" "name": "createViewQuery"
}, },
{
"name": "decreaseElementDepthCount"
},
{ {
"name": "defineComponent" "name": "defineComponent"
}, },
@ -464,15 +464,9 @@
{ {
"name": "detectChangesInternal" "name": "detectChangesInternal"
}, },
{
"name": "diPublic"
},
{ {
"name": "diPublicInInjector" "name": "diPublicInInjector"
}, },
{
"name": "directiveCreate"
},
{ {
"name": "directiveInject" "name": "directiveInject"
}, },
@ -558,7 +552,7 @@
"name": "firstTemplatePass" "name": "firstTemplatePass"
}, },
{ {
"name": "generateExpandoBlock" "name": "generateExpandoInstructionBlock"
}, },
{ {
"name": "generateInitialInputs" "name": "generateInitialInputs"
@ -569,6 +563,12 @@
{ {
"name": "getBeforeNodeForView" "name": "getBeforeNodeForView"
}, },
{
"name": "getBindingsEnabled"
},
{
"name": "getCheckNoChangesMode"
},
{ {
"name": "getCleanup" "name": "getCleanup"
}, },
@ -590,6 +590,12 @@
{ {
"name": "getContext" "name": "getContext"
}, },
{
"name": "getCreationMode"
},
{
"name": "getCurrentQueries"
},
{ {
"name": "getCurrentSanitizer" "name": "getCurrentSanitizer"
}, },
@ -602,6 +608,12 @@
{ {
"name": "getDirectiveStartIndex" "name": "getDirectiveStartIndex"
}, },
{
"name": "getElementDepthCount"
},
{
"name": "getFirstTemplatePass"
},
{ {
"name": "getHighestElementContainer" "name": "getHighestElementContainer"
}, },
@ -620,6 +632,9 @@
{ {
"name": "getInjectorIndex" "name": "getInjectorIndex"
}, },
{
"name": "getIsParent"
},
{ {
"name": "getLContainer" "name": "getLContainer"
}, },
@ -639,10 +654,10 @@
"name": "getNativeByTNode" "name": "getNativeByTNode"
}, },
{ {
"name": "getOrCreateInjectable" "name": "getNodeInjectable"
}, },
{ {
"name": "getOrCreateNodeInjector" "name": "getOrCreateInjectable"
}, },
{ {
"name": "getOrCreateNodeInjectorForNode" "name": "getOrCreateNodeInjectorForNode"
@ -653,12 +668,21 @@
{ {
"name": "getOrCreateTView" "name": "getOrCreateTView"
}, },
{
"name": "getParentInjectorIndex"
},
{ {
"name": "getParentInjectorLocation" "name": "getParentInjectorLocation"
}, },
{
"name": "getParentInjectorTNode"
},
{ {
"name": "getParentInjectorView" "name": "getParentInjectorView"
}, },
{
"name": "getParentInjectorViewOffset"
},
{ {
"name": "getParentNative" "name": "getParentNative"
}, },
@ -705,7 +729,7 @@
"name": "getRootContext" "name": "getRootContext"
}, },
{ {
"name": "getRootContext$2" "name": "getRootContext$1"
}, },
{ {
"name": "getRootView" "name": "getRootView"
@ -725,6 +749,9 @@
{ {
"name": "getTNode" "name": "getTNode"
}, },
{
"name": "getTView"
},
{ {
"name": "getTViewCleanup" "name": "getTViewCleanup"
}, },
@ -737,20 +764,35 @@
{ {
"name": "getValue" "name": "getValue"
}, },
{
"name": "getViewData"
},
{
"name": "hasParentInjector"
},
{ {
"name": "hasPlayerBuilderChanged" "name": "hasPlayerBuilderChanged"
}, },
{ {
"name": "hasValueChanged" "name": "hasValueChanged"
}, },
{
"name": "includeViewProviders"
},
{
"name": "increaseElementDepthCount"
},
{
"name": "initNodeFlags"
},
{ {
"name": "initializeTNodeInputs" "name": "initializeTNodeInputs"
}, },
{ {
"name": "inject" "name": "injectElementRef"
}, },
{ {
"name": "injectElementRef" "name": "injectRootLimpMode"
}, },
{ {
"name": "injectTemplateRef" "name": "injectTemplateRef"
@ -759,7 +801,7 @@
"name": "injectViewContainerRef" "name": "injectViewContainerRef"
}, },
{ {
"name": "injectorHasToken" "name": "insertBloom"
}, },
{ {
"name": "insertNewMultiProperty" "name": "insertNewMultiProperty"
@ -768,7 +810,10 @@
"name": "insertView" "name": "insertView"
}, },
{ {
"name": "instantiateDirectivesDirectly" "name": "instantiateAllDirectives"
},
{
"name": "instantiateRootComponent"
}, },
{ {
"name": "interpolation1" "name": "interpolation1"
@ -783,10 +828,10 @@
"name": "isComponent" "name": "isComponent"
}, },
{ {
"name": "isComponentInstance" "name": "isComponentDef"
}, },
{ {
"name": "isContentQueryHost" "name": "isComponentInstance"
}, },
{ {
"name": "isContextDirty" "name": "isContextDirty"
@ -806,6 +851,9 @@
{ {
"name": "isDirty" "name": "isDirty"
}, },
{
"name": "isFactory"
},
{ {
"name": "isJsObject" "name": "isJsObject"
}, },
@ -878,6 +926,9 @@
{ {
"name": "nextContext" "name": "nextContext"
}, },
{
"name": "nextContextImpl"
},
{ {
"name": "nextNgElementId" "name": "nextNgElementId"
}, },
@ -887,6 +938,12 @@
{ {
"name": "pointers" "name": "pointers"
}, },
{
"name": "postProcessBaseDirective"
},
{
"name": "postProcessDirective"
},
{ {
"name": "prefillHostVars" "name": "prefillHostVars"
}, },
@ -960,7 +1017,7 @@
"name": "resetComponentState" "name": "resetComponentState"
}, },
{ {
"name": "resolveDirective" "name": "resolveDirectives"
}, },
{ {
"name": "saveNameToExportMap" "name": "saveNameToExportMap"
@ -972,14 +1029,17 @@
"name": "scheduleTick" "name": "scheduleTick"
}, },
{ {
"name": "searchDirectivesOnInjector" "name": "searchTokensOnInjector"
},
{
"name": "searchMatchesQueuedForCreation"
}, },
{ {
"name": "setAnimationPlayState" "name": "setAnimationPlayState"
}, },
{
"name": "setBindingRoot"
},
{
"name": "setCheckNoChangesMode"
},
{ {
"name": "setClass" "name": "setClass"
}, },
@ -990,13 +1050,13 @@
"name": "setContextPlayersDirty" "name": "setContextPlayersDirty"
}, },
{ {
"name": "setCurrentInjector" "name": "setCurrentQueries"
}, },
{ {
"name": "setDirty" "name": "setDirty"
}, },
{ {
"name": "setEnvironment" "name": "setFirstTemplatePass"
}, },
{ {
"name": "setFlag" "name": "setFlag"
@ -1004,35 +1064,50 @@
{ {
"name": "setHostBindings" "name": "setHostBindings"
}, },
{
"name": "setIncludeViewProviders"
},
{
"name": "setInjectImplementation"
},
{ {
"name": "setInputsForProperty" "name": "setInputsForProperty"
}, },
{ {
"name": "setInputsFromAttrs" "name": "setInputsFromAttrs"
}, },
{
"name": "setIsParent"
},
{ {
"name": "setPlayerBuilder" "name": "setPlayerBuilder"
}, },
{ {
"name": "setPlayerBuilderIndex" "name": "setPlayerBuilderIndex"
}, },
{
"name": "setPreviousOrParentTNode"
},
{ {
"name": "setProp" "name": "setProp"
}, },
{
"name": "setRendererFactory"
},
{ {
"name": "setStyle" "name": "setStyle"
}, },
{ {
"name": "setUpAttributes" "name": "setTNodeAndViewData"
}, },
{ {
"name": "setUpBloom" "name": "setUpAttributes"
}, },
{ {
"name": "setValue" "name": "setValue"
}, },
{ {
"name": "shouldNotSearchParent" "name": "shouldSearchParent"
}, },
{ {
"name": "storeCleanupFn" "name": "storeCleanupFn"
@ -1061,9 +1136,6 @@
{ {
"name": "textBinding" "name": "textBinding"
}, },
{
"name": "throwCyclicDependencyError"
},
{ {
"name": "throwErrorIfNoChangesMode" "name": "throwErrorIfNoChangesMode"
}, },

View File

@ -35,6 +35,9 @@
{ {
"name": "FLAGS" "name": "FLAGS"
}, },
{
"name": "FactoryPrototype"
},
{ {
"name": "HEADER_OFFSET" "name": "HEADER_OFFSET"
}, },
@ -77,6 +80,12 @@
{ {
"name": "NO_CHANGE" "name": "NO_CHANGE"
}, },
{
"name": "NO_PARENT_INJECTOR"
},
{
"name": "NodeInjectorFactory"
},
{ {
"name": "ObjectUnsubscribedErrorImpl" "name": "ObjectUnsubscribedErrorImpl"
}, },
@ -86,9 +95,6 @@
{ {
"name": "PARENT_INJECTOR" "name": "PARENT_INJECTOR"
}, },
{
"name": "PublicFeature"
},
{ {
"name": "QUERIES" "name": "QUERIES"
}, },
@ -116,9 +122,6 @@
{ {
"name": "ViewEncapsulation$1" "name": "ViewEncapsulation$1"
}, },
{
"name": "_getViewData"
},
{ {
"name": "_renderCompCount" "name": "_renderCompCount"
}, },
@ -129,10 +132,7 @@
"name": "attachPatchData" "name": "attachPatchData"
}, },
{ {
"name": "baseDirectiveCreate" "name": "baseResolveDirective"
},
{
"name": "bindingRootIndex"
}, },
{ {
"name": "bloomAdd" "name": "bloomAdd"
@ -191,9 +191,6 @@
{ {
"name": "detectChangesInternal" "name": "detectChangesInternal"
}, },
{
"name": "diPublic"
},
{ {
"name": "diPublicInInjector" "name": "diPublicInInjector"
}, },
@ -224,6 +221,9 @@
{ {
"name": "getBeforeNodeForView" "name": "getBeforeNodeForView"
}, },
{
"name": "getCheckNoChangesMode"
},
{ {
"name": "getClosureSafeProperty" "name": "getClosureSafeProperty"
}, },
@ -236,9 +236,15 @@
{ {
"name": "getContainerRenderParent" "name": "getContainerRenderParent"
}, },
{
"name": "getCreationMode"
},
{ {
"name": "getDirectiveDef" "name": "getDirectiveDef"
}, },
{
"name": "getFirstTemplatePass"
},
{ {
"name": "getHighestElementContainer" "name": "getHighestElementContainer"
}, },
@ -248,6 +254,9 @@
{ {
"name": "getInjectorIndex" "name": "getInjectorIndex"
}, },
{
"name": "getIsParent"
},
{ {
"name": "getLContainer" "name": "getLContainer"
}, },
@ -258,7 +267,7 @@
"name": "getNativeByTNode" "name": "getNativeByTNode"
}, },
{ {
"name": "getOrCreateNodeInjector" "name": "getNodeInjectable"
}, },
{ {
"name": "getOrCreateNodeInjectorForNode" "name": "getOrCreateNodeInjectorForNode"
@ -266,12 +275,18 @@
{ {
"name": "getOrCreateTView" "name": "getOrCreateTView"
}, },
{
"name": "getParentInjectorIndex"
},
{ {
"name": "getParentInjectorLocation" "name": "getParentInjectorLocation"
}, },
{ {
"name": "getParentInjectorView" "name": "getParentInjectorView"
}, },
{
"name": "getParentInjectorViewOffset"
},
{ {
"name": "getParentNative" "name": "getParentNative"
}, },
@ -287,9 +302,42 @@
{ {
"name": "getRenderParent" "name": "getRenderParent"
}, },
{
"name": "getRenderer"
},
{
"name": "getRendererFactory"
},
{
"name": "getTView"
},
{
"name": "getViewData"
},
{
"name": "hasParentInjector"
},
{
"name": "includeViewProviders"
},
{
"name": "initNodeFlags"
},
{
"name": "insertBloom"
},
{
"name": "instantiateRootComponent"
},
{ {
"name": "invertObject" "name": "invertObject"
}, },
{
"name": "isComponentDef"
},
{
"name": "isFactory"
},
{ {
"name": "isProceduralRenderer" "name": "isProceduralRenderer"
}, },
@ -311,6 +359,9 @@
{ {
"name": "noSideEffects" "name": "noSideEffects"
}, },
{
"name": "postProcessBaseDirective"
},
{ {
"name": "prefillHostVars" "name": "prefillHostVars"
}, },
@ -350,14 +401,35 @@
{ {
"name": "resetComponentState" "name": "resetComponentState"
}, },
{
"name": "setBindingRoot"
},
{
"name": "setFirstTemplatePass"
},
{ {
"name": "setHostBindings" "name": "setHostBindings"
}, },
{ {
"name": "setUpAttributes" "name": "setIncludeViewProviders"
}, },
{ {
"name": "setUpBloom" "name": "setInjectImplementation"
},
{
"name": "setIsParent"
},
{
"name": "setPreviousOrParentTNode"
},
{
"name": "setRendererFactory"
},
{
"name": "setTNodeAndViewData"
},
{
"name": "setUpAttributes"
}, },
{ {
"name": "stringify$2" "name": "stringify$2"

View File

@ -1967,6 +1967,9 @@
{ {
"name": "__extends$p" "name": "__extends$p"
}, },
{
"name": "__forward_ref__"
},
{ {
"name": "__metadata" "name": "__metadata"
}, },
@ -3098,6 +3101,12 @@
{ {
"name": "injectArgs" "name": "injectArgs"
}, },
{
"name": "injectInjectorOnly"
},
{
"name": "injectRootLimpMode"
},
{ {
"name": "inlineInterpolate" "name": "inlineInterpolate"
}, },

View File

@ -3,7 +3,7 @@
"name": "APP_ROOT" "name": "APP_ROOT"
}, },
{ {
"name": "CIRCULAR$2" "name": "CIRCULAR$1"
}, },
{ {
"name": "EMPTY_ARRAY$2" "name": "EMPTY_ARRAY$2"
@ -68,6 +68,9 @@
{ {
"name": "_THROW_IF_NOT_FOUND" "name": "_THROW_IF_NOT_FOUND"
}, },
{
"name": "__forward_ref__"
},
{ {
"name": "__read" "name": "__read"
}, },
@ -120,7 +123,13 @@
"name": "injectArgs" "name": "injectArgs"
}, },
{ {
"name": "injectableDefRecord" "name": "injectInjectorOnly"
},
{
"name": "injectRootLimpMode"
},
{
"name": "injectableDefFactory"
}, },
{ {
"name": "isExistingProvider" "name": "isExistingProvider"
@ -143,6 +152,9 @@
{ {
"name": "makeRecord" "name": "makeRecord"
}, },
{
"name": "providerToFactory"
},
{ {
"name": "providerToRecord" "name": "providerToRecord"
}, },

View File

@ -11,9 +11,6 @@
{ {
"name": "BoundPlayerFactory" "name": "BoundPlayerFactory"
}, },
{
"name": "CIRCULAR$1"
},
{ {
"name": "CLEANUP" "name": "CLEANUP"
}, },
@ -59,6 +56,9 @@
{ {
"name": "FLAGS" "name": "FLAGS"
}, },
{
"name": "FactoryPrototype"
},
{ {
"name": "HEADER_OFFSET" "name": "HEADER_OFFSET"
}, },
@ -107,9 +107,15 @@
{ {
"name": "NG_PROJECT_AS_ATTR_NAME" "name": "NG_PROJECT_AS_ATTR_NAME"
}, },
{
"name": "NOT_FOUND"
},
{ {
"name": "NO_CHANGE" "name": "NO_CHANGE"
}, },
{
"name": "NO_PARENT_INJECTOR"
},
{ {
"name": "NgForOf" "name": "NgForOf"
}, },
@ -128,6 +134,9 @@
{ {
"name": "NodeInjector" "name": "NodeInjector"
}, },
{
"name": "NodeInjectorFactory"
},
{ {
"name": "NullInjector" "name": "NullInjector"
}, },
@ -146,9 +155,6 @@
{ {
"name": "PARENT_INJECTOR" "name": "PARENT_INJECTOR"
}, },
{
"name": "PublicFeature"
},
{ {
"name": "QUERIES" "name": "QUERIES"
}, },
@ -329,18 +335,12 @@
{ {
"name": "_c9" "name": "_c9"
}, },
{
"name": "_currentInjector"
},
{ {
"name": "_currentNamespace" "name": "_currentNamespace"
}, },
{ {
"name": "_devMode" "name": "_devMode"
}, },
{
"name": "_getViewData"
},
{ {
"name": "_global" "name": "_global"
}, },
@ -378,14 +378,11 @@
"name": "attachPatchData" "name": "attachPatchData"
}, },
{ {
"name": "baseDirectiveCreate" "name": "baseResolveDirective"
}, },
{ {
"name": "bind" "name": "bind"
}, },
{
"name": "bindingRootIndex"
},
{ {
"name": "bindingUpdated" "name": "bindingUpdated"
}, },
@ -393,10 +390,10 @@
"name": "bloomAdd" "name": "bloomAdd"
}, },
{ {
"name": "bloomHashBitOrFactory" "name": "bloomHasToken"
}, },
{ {
"name": "cacheMatchingDirectivesForNode" "name": "bloomHashBitOrFactory"
}, },
{ {
"name": "cacheMatchingLocalNames" "name": "cacheMatchingLocalNames"
@ -494,6 +491,9 @@
{ {
"name": "createViewQuery" "name": "createViewQuery"
}, },
{
"name": "decreaseElementDepthCount"
},
{ {
"name": "defineComponent" "name": "defineComponent"
}, },
@ -521,15 +521,9 @@
{ {
"name": "detectChangesInternal" "name": "detectChangesInternal"
}, },
{
"name": "diPublic"
},
{ {
"name": "diPublicInInjector" "name": "diPublicInInjector"
}, },
{
"name": "directiveCreate"
},
{ {
"name": "directiveInject" "name": "directiveInject"
}, },
@ -603,7 +597,7 @@
"name": "firstTemplatePass" "name": "firstTemplatePass"
}, },
{ {
"name": "generateExpandoBlock" "name": "generateExpandoInstructionBlock"
}, },
{ {
"name": "generateInitialInputs" "name": "generateInitialInputs"
@ -614,6 +608,12 @@
{ {
"name": "getBeforeNodeForView" "name": "getBeforeNodeForView"
}, },
{
"name": "getBindingsEnabled"
},
{
"name": "getCheckNoChangesMode"
},
{ {
"name": "getCleanup" "name": "getCleanup"
}, },
@ -632,6 +632,15 @@
{ {
"name": "getContainerRenderParent" "name": "getContainerRenderParent"
}, },
{
"name": "getContextViewData"
},
{
"name": "getCreationMode"
},
{
"name": "getCurrentQueries"
},
{ {
"name": "getCurrentSanitizer" "name": "getCurrentSanitizer"
}, },
@ -641,6 +650,12 @@
{ {
"name": "getDirectiveDef" "name": "getDirectiveDef"
}, },
{
"name": "getElementDepthCount"
},
{
"name": "getFirstTemplatePass"
},
{ {
"name": "getHighestElementContainer" "name": "getHighestElementContainer"
}, },
@ -659,6 +674,9 @@
{ {
"name": "getInjectorIndex" "name": "getInjectorIndex"
}, },
{
"name": "getIsParent"
},
{ {
"name": "getLContainer" "name": "getLContainer"
}, },
@ -678,10 +696,10 @@
"name": "getNativeByTNode" "name": "getNativeByTNode"
}, },
{ {
"name": "getOrCreateInjectable" "name": "getNodeInjectable"
}, },
{ {
"name": "getOrCreateNodeInjector" "name": "getOrCreateInjectable"
}, },
{ {
"name": "getOrCreateNodeInjectorForNode" "name": "getOrCreateNodeInjectorForNode"
@ -689,12 +707,21 @@
{ {
"name": "getOrCreateTView" "name": "getOrCreateTView"
}, },
{
"name": "getParentInjectorIndex"
},
{ {
"name": "getParentInjectorLocation" "name": "getParentInjectorLocation"
}, },
{
"name": "getParentInjectorTNode"
},
{ {
"name": "getParentInjectorView" "name": "getParentInjectorView"
}, },
{
"name": "getParentInjectorViewOffset"
},
{ {
"name": "getParentNative" "name": "getParentNative"
}, },
@ -755,6 +782,9 @@
{ {
"name": "getTNode" "name": "getTNode"
}, },
{
"name": "getTView"
},
{ {
"name": "getTViewCleanup" "name": "getTViewCleanup"
}, },
@ -767,20 +797,35 @@
{ {
"name": "getValue" "name": "getValue"
}, },
{
"name": "getViewData"
},
{
"name": "hasParentInjector"
},
{ {
"name": "hasPlayerBuilderChanged" "name": "hasPlayerBuilderChanged"
}, },
{ {
"name": "hasValueChanged" "name": "hasValueChanged"
}, },
{
"name": "includeViewProviders"
},
{
"name": "increaseElementDepthCount"
},
{
"name": "initNodeFlags"
},
{ {
"name": "initializeTNodeInputs" "name": "initializeTNodeInputs"
}, },
{ {
"name": "inject" "name": "injectElementRef"
}, },
{ {
"name": "injectElementRef" "name": "injectRootLimpMode"
}, },
{ {
"name": "injectTemplateRef" "name": "injectTemplateRef"
@ -789,13 +834,16 @@
"name": "injectViewContainerRef" "name": "injectViewContainerRef"
}, },
{ {
"name": "injectorHasToken" "name": "insertBloom"
}, },
{ {
"name": "insertView" "name": "insertView"
}, },
{ {
"name": "instantiateDirectivesDirectly" "name": "instantiateAllDirectives"
},
{
"name": "instantiateRootComponent"
}, },
{ {
"name": "interpolation1" "name": "interpolation1"
@ -807,7 +855,7 @@
"name": "isComponent" "name": "isComponent"
}, },
{ {
"name": "isContentQueryHost" "name": "isComponentDef"
}, },
{ {
"name": "isContextDirty" "name": "isContextDirty"
@ -824,6 +872,9 @@
{ {
"name": "isDirty" "name": "isDirty"
}, },
{
"name": "isFactory"
},
{ {
"name": "isJsObject" "name": "isJsObject"
}, },
@ -893,6 +944,9 @@
{ {
"name": "nextContext" "name": "nextContext"
}, },
{
"name": "nextContextImpl"
},
{ {
"name": "nextNgElementId" "name": "nextNgElementId"
}, },
@ -902,6 +956,12 @@
{ {
"name": "pointers" "name": "pointers"
}, },
{
"name": "postProcessBaseDirective"
},
{
"name": "postProcessDirective"
},
{ {
"name": "prefillHostVars" "name": "prefillHostVars"
}, },
@ -978,7 +1038,7 @@
"name": "resetComponentState" "name": "resetComponentState"
}, },
{ {
"name": "resolveDirective" "name": "resolveDirectives"
}, },
{ {
"name": "restoreView" "name": "restoreView"
@ -993,10 +1053,13 @@
"name": "scheduleTick" "name": "scheduleTick"
}, },
{ {
"name": "searchDirectivesOnInjector" "name": "searchTokensOnInjector"
}, },
{ {
"name": "searchMatchesQueuedForCreation" "name": "setBindingRoot"
},
{
"name": "setCheckNoChangesMode"
}, },
{ {
"name": "setClass" "name": "setClass"
@ -1008,13 +1071,13 @@
"name": "setContextPlayersDirty" "name": "setContextPlayersDirty"
}, },
{ {
"name": "setCurrentInjector" "name": "setCurrentQueries"
}, },
{ {
"name": "setDirty" "name": "setDirty"
}, },
{ {
"name": "setEnvironment" "name": "setFirstTemplatePass"
}, },
{ {
"name": "setFlag" "name": "setFlag"
@ -1022,35 +1085,50 @@
{ {
"name": "setHostBindings" "name": "setHostBindings"
}, },
{
"name": "setIncludeViewProviders"
},
{
"name": "setInjectImplementation"
},
{ {
"name": "setInputsForProperty" "name": "setInputsForProperty"
}, },
{ {
"name": "setInputsFromAttrs" "name": "setInputsFromAttrs"
}, },
{
"name": "setIsParent"
},
{ {
"name": "setPlayerBuilder" "name": "setPlayerBuilder"
}, },
{ {
"name": "setPlayerBuilderIndex" "name": "setPlayerBuilderIndex"
}, },
{
"name": "setPreviousOrParentTNode"
},
{ {
"name": "setProp" "name": "setProp"
}, },
{
"name": "setRendererFactory"
},
{ {
"name": "setStyle" "name": "setStyle"
}, },
{ {
"name": "setUpAttributes" "name": "setTNodeAndViewData"
}, },
{ {
"name": "setUpBloom" "name": "setUpAttributes"
}, },
{ {
"name": "setValue" "name": "setValue"
}, },
{ {
"name": "shouldNotSearchParent" "name": "shouldSearchParent"
}, },
{ {
"name": "storeCleanupFn" "name": "storeCleanupFn"
@ -1076,9 +1154,6 @@
{ {
"name": "textBinding" "name": "textBinding"
}, },
{
"name": "throwCyclicDependencyError"
},
{ {
"name": "throwErrorIfNoChangesMode" "name": "throwErrorIfNoChangesMode"
}, },

View File

@ -80,9 +80,6 @@
{ {
"name": "CIRCULAR$1" "name": "CIRCULAR$1"
}, },
{
"name": "CIRCULAR$2"
},
{ {
"name": "CLEANUP" "name": "CLEANUP"
}, },
@ -308,6 +305,9 @@
{ {
"name": "FLAGS" "name": "FLAGS"
}, },
{
"name": "FactoryPrototype"
},
{ {
"name": "FormStyle" "name": "FormStyle"
}, },
@ -500,6 +500,9 @@
{ {
"name": "NON_ALPHANUMERIC_REGEXP" "name": "NON_ALPHANUMERIC_REGEXP"
}, },
{
"name": "NOT_FOUND"
},
{ {
"name": "NOT_YET" "name": "NOT_YET"
}, },
@ -509,6 +512,9 @@
{ {
"name": "NO_NEW_LINE" "name": "NO_NEW_LINE"
}, },
{
"name": "NO_PARENT_INJECTOR"
},
{ {
"name": "NULL_INJECTOR" "name": "NULL_INJECTOR"
}, },
@ -587,6 +593,9 @@
{ {
"name": "NodeInjector" "name": "NodeInjector"
}, },
{
"name": "NodeInjectorFactory"
},
{ {
"name": "NoopNgZone" "name": "NoopNgZone"
}, },
@ -668,9 +677,6 @@
{ {
"name": "Plural" "name": "Plural"
}, },
{
"name": "PublicFeature"
},
{ {
"name": "QUERIES" "name": "QUERIES"
}, },
@ -998,6 +1004,9 @@
{ {
"name": "__extends$p" "name": "__extends$p"
}, },
{
"name": "__forward_ref__"
},
{ {
"name": "__read" "name": "__read"
}, },
@ -1115,9 +1124,6 @@
{ {
"name": "_enable_super_gross_mode_that_will_cause_bad_things" "name": "_enable_super_gross_mode_that_will_cause_bad_things"
}, },
{
"name": "_getViewData"
},
{ {
"name": "_global" "name": "_global"
}, },
@ -1184,9 +1190,6 @@
{ {
"name": "addToViewTree" "name": "addToViewTree"
}, },
{
"name": "adjustBlueprintForNewNode"
},
{ {
"name": "allocPlayerContext" "name": "allocPlayerContext"
}, },
@ -1208,17 +1211,14 @@
{ {
"name": "attachPatchData" "name": "attachPatchData"
}, },
{
"name": "baseDirectiveCreate"
},
{ {
"name": "baseElement" "name": "baseElement"
}, },
{ {
"name": "bind" "name": "baseResolveDirective"
}, },
{ {
"name": "bindingRootIndex" "name": "bind"
}, },
{ {
"name": "bindingUpdated" "name": "bindingUpdated"
@ -1230,10 +1230,10 @@
"name": "bloomAdd" "name": "bloomAdd"
}, },
{ {
"name": "bloomHashBitOrFactory" "name": "bloomHasToken"
}, },
{ {
"name": "cacheMatchingDirectivesForNode" "name": "bloomHashBitOrFactory"
}, },
{ {
"name": "cacheMatchingLocalNames" "name": "cacheMatchingLocalNames"
@ -1394,6 +1394,9 @@
{ {
"name": "decoratePreventDefault" "name": "decoratePreventDefault"
}, },
{
"name": "decreaseElementDepthCount"
},
{ {
"name": "deepForEach" "name": "deepForEach"
}, },
@ -1451,15 +1454,9 @@
{ {
"name": "detectWTF" "name": "detectWTF"
}, },
{
"name": "diPublic"
},
{ {
"name": "diPublicInInjector" "name": "diPublicInInjector"
}, },
{
"name": "directiveCreate"
},
{ {
"name": "directiveInject" "name": "directiveInject"
}, },
@ -1605,7 +1602,7 @@
"name": "fromPromise" "name": "fromPromise"
}, },
{ {
"name": "generateExpandoBlock" "name": "generateExpandoInstructionBlock"
}, },
{ {
"name": "generateInitialInputs" "name": "generateInitialInputs"
@ -1619,6 +1616,12 @@
{ {
"name": "getBeforeNodeForView" "name": "getBeforeNodeForView"
}, },
{
"name": "getBindingsEnabled"
},
{
"name": "getCheckNoChangesMode"
},
{ {
"name": "getCleanup" "name": "getCleanup"
}, },
@ -1637,9 +1640,18 @@
{ {
"name": "getContainerRenderParent" "name": "getContainerRenderParent"
}, },
{
"name": "getContextViewData"
},
{
"name": "getCreationMode"
},
{ {
"name": "getCurrencySymbol" "name": "getCurrencySymbol"
}, },
{
"name": "getCurrentQueries"
},
{ {
"name": "getCurrentSanitizer" "name": "getCurrentSanitizer"
}, },
@ -1667,9 +1679,15 @@
{ {
"name": "getDirectiveDef" "name": "getDirectiveDef"
}, },
{
"name": "getElementDepthCount"
},
{ {
"name": "getErrorLogger" "name": "getErrorLogger"
}, },
{
"name": "getFirstTemplatePass"
},
{ {
"name": "getFirstThursdayOfYear" "name": "getFirstThursdayOfYear"
}, },
@ -1694,6 +1712,9 @@
{ {
"name": "getInjectorIndex" "name": "getInjectorIndex"
}, },
{
"name": "getIsParent"
},
{ {
"name": "getLContainer" "name": "getLContainer"
}, },
@ -1766,6 +1787,9 @@
{ {
"name": "getNgZone" "name": "getNgZone"
}, },
{
"name": "getNodeInjectable"
},
{ {
"name": "getNullInjector" "name": "getNullInjector"
}, },
@ -1775,9 +1799,6 @@
{ {
"name": "getOrCreateInjectable" "name": "getOrCreateInjectable"
}, },
{
"name": "getOrCreateNodeInjector"
},
{ {
"name": "getOrCreateNodeInjectorForNode" "name": "getOrCreateNodeInjectorForNode"
}, },
@ -1790,12 +1811,21 @@
{ {
"name": "getOriginalError" "name": "getOriginalError"
}, },
{
"name": "getParentInjectorIndex"
},
{ {
"name": "getParentInjectorLocation" "name": "getParentInjectorLocation"
}, },
{
"name": "getParentInjectorTNode"
},
{ {
"name": "getParentInjectorView" "name": "getParentInjectorView"
}, },
{
"name": "getParentInjectorViewOffset"
},
{ {
"name": "getParentNative" "name": "getParentNative"
}, },
@ -1868,6 +1898,9 @@
{ {
"name": "getTNode" "name": "getTNode"
}, },
{
"name": "getTView"
},
{ {
"name": "getTViewCleanup" "name": "getTViewCleanup"
}, },
@ -1886,6 +1919,9 @@
{ {
"name": "getValue" "name": "getValue"
}, },
{
"name": "getViewData"
},
{ {
"name": "globalListener" "name": "globalListener"
}, },
@ -1898,6 +1934,9 @@
{ {
"name": "hasOnDestroy" "name": "hasOnDestroy"
}, },
{
"name": "hasParentInjector"
},
{ {
"name": "hasPlayerBuilderChanged" "name": "hasPlayerBuilderChanged"
}, },
@ -1910,9 +1949,18 @@
{ {
"name": "identity" "name": "identity"
}, },
{
"name": "includeViewProviders"
},
{
"name": "increaseElementDepthCount"
},
{ {
"name": "initDomAdapter" "name": "initDomAdapter"
}, },
{
"name": "initNodeFlags"
},
{ {
"name": "initializeTNodeInputs" "name": "initializeTNodeInputs"
}, },
@ -1925,15 +1973,24 @@
{ {
"name": "injectAttribute" "name": "injectAttribute"
}, },
{
"name": "injectAttributeImpl"
},
{ {
"name": "injectChangeDetectorRef" "name": "injectChangeDetectorRef"
}, },
{ {
"name": "injectElementRef" "name": "injectElementRef"
}, },
{
"name": "injectInjectorOnly"
},
{ {
"name": "injectRenderer2" "name": "injectRenderer2"
}, },
{
"name": "injectRootLimpMode"
},
{ {
"name": "injectTemplateRef" "name": "injectTemplateRef"
}, },
@ -1941,10 +1998,10 @@
"name": "injectViewContainerRef" "name": "injectViewContainerRef"
}, },
{ {
"name": "injectableDefRecord" "name": "injectableDefFactory"
}, },
{ {
"name": "injectorHasToken" "name": "insertBloom"
}, },
{ {
"name": "insertView" "name": "insertView"
@ -1953,7 +2010,10 @@
"name": "inspectNativeElement" "name": "inspectNativeElement"
}, },
{ {
"name": "instantiateDirectivesDirectly" "name": "instantiateAllDirectives"
},
{
"name": "instantiateRootComponent"
}, },
{ {
"name": "interpolation1" "name": "interpolation1"
@ -1977,7 +2037,7 @@
"name": "isComponent" "name": "isComponent"
}, },
{ {
"name": "isContentQueryHost" "name": "isComponentDef"
}, },
{ {
"name": "isContextDirty" "name": "isContextDirty"
@ -2006,6 +2066,9 @@
{ {
"name": "isExistingProvider" "name": "isExistingProvider"
}, },
{
"name": "isFactory"
},
{ {
"name": "isFactoryProvider" "name": "isFactoryProvider"
}, },
@ -2153,6 +2216,9 @@
{ {
"name": "nextContext" "name": "nextContext"
}, },
{
"name": "nextContextImpl"
},
{ {
"name": "nextNgElementId" "name": "nextNgElementId"
}, },
@ -2216,6 +2282,12 @@
{ {
"name": "pointers" "name": "pointers"
}, },
{
"name": "postProcessBaseDirective"
},
{
"name": "postProcessDirective"
},
{ {
"name": "prefillHostVars" "name": "prefillHostVars"
}, },
@ -2228,6 +2300,9 @@
{ {
"name": "promise" "name": "promise"
}, },
{
"name": "providerToFactory"
},
{ {
"name": "providerToRecord" "name": "providerToRecord"
}, },
@ -2307,7 +2382,7 @@
"name": "resetComponentState" "name": "resetComponentState"
}, },
{ {
"name": "resolveDirective" "name": "resolveDirectives"
}, },
{ {
"name": "resolveForwardRef$1" "name": "resolveForwardRef$1"
@ -2343,10 +2418,13 @@
"name": "scheduleTick" "name": "scheduleTick"
}, },
{ {
"name": "searchDirectivesOnInjector" "name": "searchTokensOnInjector"
}, },
{ {
"name": "searchMatchesQueuedForCreation" "name": "setBindingRoot"
},
{
"name": "setCheckNoChangesMode"
}, },
{ {
"name": "setClass" "name": "setClass"
@ -2360,11 +2438,14 @@
{ {
"name": "setCurrentInjector" "name": "setCurrentInjector"
}, },
{
"name": "setCurrentQueries"
},
{ {
"name": "setDirty" "name": "setDirty"
}, },
{ {
"name": "setEnvironment" "name": "setFirstTemplatePass"
}, },
{ {
"name": "setFlag" "name": "setFlag"
@ -2372,36 +2453,51 @@
{ {
"name": "setHostBindings" "name": "setHostBindings"
}, },
{
"name": "setIncludeViewProviders"
},
{
"name": "setInjectImplementation"
},
{ {
"name": "setInputsForProperty" "name": "setInputsForProperty"
}, },
{ {
"name": "setInputsFromAttrs" "name": "setInputsFromAttrs"
}, },
{
"name": "setIsParent"
},
{ {
"name": "setPlayerBuilder" "name": "setPlayerBuilder"
}, },
{ {
"name": "setPlayerBuilderIndex" "name": "setPlayerBuilderIndex"
}, },
{
"name": "setPreviousOrParentTNode"
},
{ {
"name": "setProp" "name": "setProp"
}, },
{
"name": "setRendererFactory"
},
{ {
"name": "setRootDomAdapter" "name": "setRootDomAdapter"
}, },
{ {
"name": "setStyle" "name": "setStyle"
}, },
{
"name": "setTNodeAndViewData"
},
{ {
"name": "setTestabilityGetter" "name": "setTestabilityGetter"
}, },
{ {
"name": "setUpAttributes" "name": "setUpAttributes"
}, },
{
"name": "setUpBloom"
},
{ {
"name": "setValue" "name": "setValue"
}, },
@ -2418,7 +2514,7 @@
"name": "shimHostAttribute" "name": "shimHostAttribute"
}, },
{ {
"name": "shouldNotSearchParent" "name": "shouldSearchParent"
}, },
{ {
"name": "staticError" "name": "staticError"
@ -2483,9 +2579,6 @@
{ {
"name": "textBinding" "name": "textBinding"
}, },
{
"name": "throwCyclicDependencyError"
},
{ {
"name": "throwErrorIfNoChangesMode" "name": "throwErrorIfNoChangesMode"
}, },

View File

@ -397,7 +397,7 @@ describe('InheritDefinitionFeature', () => {
const subDef = SubDirective.ngDirectiveDef as DirectiveDef<any>; const subDef = SubDirective.ngDirectiveDef as DirectiveDef<any>;
subDef.contentQueries !(); subDef.contentQueries !(0);
expect(log).toEqual(['super', 'sub']); expect(log).toEqual(['super', 'sub']);
}); });

View File

@ -11,9 +11,8 @@ import {withBody} from '@angular/private/testing';
import {ChangeDetectionStrategy, ChangeDetectorRef, DoCheck, RendererType2} from '../../src/core'; import {ChangeDetectionStrategy, ChangeDetectorRef, DoCheck, RendererType2} from '../../src/core';
import {getRenderedText, whenRendered} from '../../src/render3/component'; import {getRenderedText, whenRendered} from '../../src/render3/component';
import {directiveInject} from '../../src/render3/di';
import {LifecycleHooksFeature, defineComponent, defineDirective, templateRefExtractor} from '../../src/render3/index'; import {LifecycleHooksFeature, defineComponent, defineDirective, templateRefExtractor} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, detectChanges, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, listener, markDirty, reference, text, template, textBinding, tick} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, detectChanges, directiveInject, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, listener, markDirty, reference, text, template, textBinding, tick} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition'; import {RenderFlags} from '../../src/render3/interfaces/definition';
import {RElement, Renderer3, RendererFactory3} from '../../src/render3/interfaces/renderer'; import {RElement, Renderer3, RendererFactory3} from '../../src/render3/interfaces/renderer';

View File

@ -10,8 +10,9 @@ import {NgForOfContext} from '@angular/common';
import {ElementRef, TemplateRef} from '@angular/core'; import {ElementRef, TemplateRef} from '@angular/core';
import {AttributeMarker, defineComponent, templateRefExtractor} from '../../src/render3/index'; import {AttributeMarker, defineComponent, templateRefExtractor} from '../../src/render3/index';
import {bind, template, elementEnd, elementProperty, elementStart, getCurrentView, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, restoreView, text, textBinding, elementContainerStart, elementContainerEnd, reference} from '../../src/render3/instructions'; import {bind, template, elementEnd, elementProperty, elementStart, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, text, textBinding, elementContainerStart, elementContainerEnd, reference} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition'; import {RenderFlags} from '../../src/render3/interfaces/definition';
import {getCurrentView, restoreView} from '../../src/render3/state';
import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def'; import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def';
import {ComponentFixture} from './render_util'; import {ComponentFixture} from './render_util';

View File

@ -31,7 +31,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: ChildComponent, type: ChildComponent,
selectors: [['child']], selectors: [['child']],
factory: function ChildComponent_Factory() { return new ChildComponent(); }, factory: function ChildComponent_Factory(t) { return new (t || ChildComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function ChildComponent_Template(rf: $RenderFlags$, ctx: $ChildComponent$) { template: function ChildComponent_Template(rf: $RenderFlags$, ctx: $ChildComponent$) {
@ -52,7 +52,7 @@ describe('components & directives', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: SomeDirective, type: SomeDirective,
selectors: [['', 'some-directive', '']], selectors: [['', 'some-directive', '']],
factory: () => new SomeDirective(), factory: function SomeDirective_Factory(t) { return new (t || SomeDirective)(); },
}); });
// /NORMATIVE // /NORMATIVE
} }
@ -68,7 +68,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: () => new MyComponent(), factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function(rf: $RenderFlags$, ctx: $MyComponent$) { template: function(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -101,7 +101,7 @@ describe('components & directives', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: HostBindingDir, type: HostBindingDir,
selectors: [['', 'hostBindingDir', '']], selectors: [['', 'hostBindingDir', '']],
factory: function HostBindingDir_Factory() { return new HostBindingDir(); }, factory: function HostBindingDir_Factory(t) { return new (t || HostBindingDir)(); },
hostVars: 1, hostVars: 1,
hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) { hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) {
$r3$.ɵelementProperty( $r3$.ɵelementProperty(
@ -123,7 +123,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -175,7 +175,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -205,7 +205,7 @@ describe('components & directives', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
selectors: [['', 'hostAttributeDir', '']], selectors: [['', 'hostAttributeDir', '']],
type: HostAttributeDir, type: HostAttributeDir,
factory: function HostAttributeDir_Factory() { return new HostAttributeDir(); }, factory: function HostAttributeDir_Factory(t) { return new (t || HostAttributeDir)(); },
attributes: ['role', 'listbox'] attributes: ['role', 'listbox']
}); });
// /NORMATIVE // /NORMATIVE
@ -223,7 +223,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -252,7 +252,7 @@ describe('components & directives', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: HostBindingDir, type: HostBindingDir,
selectors: [['', 'hostBindingDir', '']], selectors: [['', 'hostBindingDir', '']],
factory: function HostBindingDir_Factory() { return new HostBindingDir(); }, factory: function HostBindingDir_Factory(t) { return new (t || HostBindingDir)(); },
hostVars: 1, hostVars: 1,
hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) { hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) {
$r3$.ɵelementAttribute( $r3$.ɵelementAttribute(
@ -274,7 +274,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -311,7 +311,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp(); }, factory: function MyComp_Factory(t) { return new (t || MyComp)(); },
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) { template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) {
@ -340,7 +340,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -388,7 +388,9 @@ describe('components & directives', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: IfDirective, type: IfDirective,
selectors: [['', 'if', '']], selectors: [['', 'if', '']],
factory: () => new IfDirective($r3$.ɵdirectiveInject(TemplateRef as any)), factory: function IfDirective_Factory(t) {
return new (t || IfDirective)($r3$.ɵdirectiveInject(TemplateRef as any));
},
}); });
// /NORMATIVE // /NORMATIVE
} }
@ -406,7 +408,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: () => new MyComponent(), factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 3, consts: 3,
vars: 0, vars: 0,
template: function(rf: $RenderFlags$, ctx: $MyComponent$) { template: function(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -440,7 +442,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyArrayComp, type: MyArrayComp,
selectors: [['my-array-comp']], selectors: [['my-array-comp']],
factory: function MyArrayComp_Factory() { return new MyArrayComp(); }, factory: function MyArrayComp_Factory(t) { return new (t || MyArrayComp)(); },
consts: 1, consts: 1,
vars: 2, vars: 2,
template: function MyArrayComp_Template(rf: $RenderFlags$, ctx: $MyArrayComp$) { template: function MyArrayComp_Template(rf: $RenderFlags$, ctx: $MyArrayComp$) {
@ -473,7 +475,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -519,7 +521,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 2, vars: 2,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -555,7 +557,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp(); }, factory: function MyComp_Factory(t) { return new (t || MyComp)(); },
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) { template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) {
@ -589,7 +591,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 2, vars: 2,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -634,7 +636,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 3, vars: 3,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -684,7 +686,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp(); }, factory: function MyComp_Factory(t) { return new (t || MyComp)(); },
consts: 12, consts: 12,
vars: 12, vars: 12,
template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) { template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) {
@ -749,7 +751,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 11, vars: 11,
template: function MyApp_Template(rf: $RenderFlags$, c: $any$) { template: function MyApp_Template(rf: $RenderFlags$, c: $any$) {
@ -793,7 +795,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: ObjectComp, type: ObjectComp,
selectors: [['object-comp']], selectors: [['object-comp']],
factory: function ObjectComp_Factory() { return new ObjectComp(); }, factory: function ObjectComp_Factory(t) { return new (t || ObjectComp)(); },
consts: 4, consts: 4,
vars: 2, vars: 2,
template: function ObjectComp_Template(rf: $RenderFlags$, ctx: $ObjectComp$) { template: function ObjectComp_Template(rf: $RenderFlags$, ctx: $ObjectComp$) {
@ -831,7 +833,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 3, vars: 3,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -874,7 +876,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: NestedComp, type: NestedComp,
selectors: [['nested-comp']], selectors: [['nested-comp']],
factory: function NestedComp_Factory() { return new NestedComp(); }, factory: function NestedComp_Factory(t) { return new (t || NestedComp)(); },
consts: 6, consts: 6,
vars: 3, vars: 3,
template: function NestedComp_Template(rf: $RenderFlags$, ctx: $NestedComp$) { template: function NestedComp_Template(rf: $RenderFlags$, ctx: $NestedComp$) {
@ -921,7 +923,7 @@ describe('components & directives', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 8, vars: 8,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {

View File

@ -24,7 +24,7 @@ describe('content projection', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: SimpleComponent, type: SimpleComponent,
selectors: [['simple']], selectors: [['simple']],
factory: () => new SimpleComponent(), factory: function SimpleComponent_Factory(t) { return new (t || SimpleComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function(rf: $RenderFlags$, ctx: $SimpleComponent$) { template: function(rf: $RenderFlags$, ctx: $SimpleComponent$) {
@ -55,7 +55,7 @@ describe('content projection', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: ComplexComponent, type: ComplexComponent,
selectors: [['complex']], selectors: [['complex']],
factory: () => new ComplexComponent(), factory: function ComplexComponent_Factory(t) { return new (t || ComplexComponent)(); },
consts: 4, consts: 4,
vars: 0, vars: 0,
template: function(rf: $RenderFlags$, ctx: $ComplexComponent$) { template: function(rf: $RenderFlags$, ctx: $ComplexComponent$) {
@ -80,7 +80,7 @@ describe('content projection', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: () => new MyApp(), factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function(rf: $RenderFlags$, ctx: $MyApp$) { template: function(rf: $RenderFlags$, ctx: $MyApp$) {

View File

@ -34,7 +34,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: () => new MyComponent(), factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 5, consts: 5,
vars: 0, vars: 0,
template: function(rf: $RenderFlags$, ctx: $MyComponent$) { template: function(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -65,7 +65,7 @@ describe('elements', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: Dir, type: Dir,
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
factory: function DirA_Factory() { return new Dir(); }, factory: function DirA_Factory(t) { return new (t || Dir)(); },
exportAs: 'dir' exportAs: 'dir'
}); });
} }
@ -87,7 +87,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: LocalRefComp, type: LocalRefComp,
selectors: [['local-ref-comp']], selectors: [['local-ref-comp']],
factory: function LocalRefComp_Factory() { return new LocalRefComp(); }, factory: function LocalRefComp_Factory(t) { return new (t || LocalRefComp)(); },
consts: 4, consts: 4,
vars: 2, vars: 2,
template: function LocalRefComp_Template(rf: $RenderFlags$, ctx: $LocalRefComp$) { template: function LocalRefComp_Template(rf: $RenderFlags$, ctx: $LocalRefComp$) {
@ -131,7 +131,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: ListenerComp, type: ListenerComp,
selectors: [['listener-comp']], selectors: [['listener-comp']],
factory: function ListenerComp_Factory() { return new ListenerComp(); }, factory: function ListenerComp_Factory(t) { return new (t || ListenerComp)(); },
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function ListenerComp_Template(rf: $RenderFlags$, ctx: $ListenerComp$) { template: function ListenerComp_Template(rf: $RenderFlags$, ctx: $ListenerComp$) {
@ -188,7 +188,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: () => new MyComponent(), factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 5, consts: 5,
vars: 0, vars: 0,
template: function(rf: $RenderFlags$, ctx: $MyComponent$) { template: function(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -222,7 +222,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) { template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -255,7 +255,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) { template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -289,7 +289,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) { template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -334,7 +334,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) { template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -379,7 +379,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) { template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -419,7 +419,7 @@ describe('elements', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: StyleComponent, type: StyleComponent,
selectors: [['style-comp']], selectors: [['style-comp']],
factory: function StyleComponent_Factory() { return new StyleComponent(); }, factory: function StyleComponent_Factory(t) { return new (t || StyleComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function StyleComponent_Template(rf: $RenderFlags$, ctx: $StyleComponent$) { template: function StyleComponent_Template(rf: $RenderFlags$, ctx: $StyleComponent$) {

View File

@ -25,7 +25,7 @@ describe('i18n', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: () => new MyApp(), factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function(rf: $RenderFlags$, ctx: $MyApp$) { template: function(rf: $RenderFlags$, ctx: $MyApp$) {
@ -52,7 +52,7 @@ describe('i18n', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: () => new MyApp(), factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function(rf: $RenderFlags$, ctx: $MyApp$) { template: function(rf: $RenderFlags$, ctx: $MyApp$) {
@ -81,7 +81,7 @@ describe('i18n', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: () => new MyApp(), factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function(rf: $RenderFlags$, ctx: $MyApp$) { template: function(rf: $RenderFlags$, ctx: $MyApp$) {
@ -125,7 +125,7 @@ describe('i18n', () => {
items: string[] = ['1', '2']; items: string[] = ['1', '2'];
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
factory: () => new MyApp(), factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
selectors: [['my-app']], selectors: [['my-app']],
consts: 2, consts: 2,
vars: 1, vars: 1,

View File

@ -8,6 +8,7 @@
import {Attribute, ChangeDetectorRef, Component, INJECTOR, Inject, InjectFlags, Injectable, Injector, SkipSelf, defineInjectable, inject} from '../../../src/core'; import {Attribute, ChangeDetectorRef, Component, INJECTOR, Inject, InjectFlags, Injectable, Injector, SkipSelf, defineInjectable, inject} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export'; import * as $r3$ from '../../../src/core_render3_private_export';
import {ProvidersFeature} from '../../../src/render3/features/providers_feature';
import {renderComponent, toHtml} from '../render_util'; import {renderComponent, toHtml} from '../render_util';
@ -31,8 +32,8 @@ describe('injection', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: function MyComp_Factory() { factory: function MyComp_Factory(t) {
return new MyComp($r3$.ɵdirectiveInject(ChangeDetectorRef as any)); return new (t || MyComp)($r3$.ɵdirectiveInject(ChangeDetectorRef as any));
}, },
consts: 1, consts: 1,
vars: 1, vars: 1,
@ -52,7 +53,7 @@ describe('injection', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
/** <my-comp></my-comp> */ /** <my-comp></my-comp> */
@ -83,7 +84,9 @@ describe('injection', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: function MyComp_Factory() { return new MyComp($r3$.ɵinjectAttribute('title')); }, factory: function MyComp_Factory(t) {
return new (t || MyComp)($r3$.ɵinjectAttribute('title'));
},
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) { template: function MyComp_Template(rf: $RenderFlags$, ctx: $MyComp$) {
@ -102,7 +105,7 @@ describe('injection', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
/** <my-comp></my-comp> */ /** <my-comp></my-comp> */
@ -153,15 +156,14 @@ describe('injection', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { factory: function MyApp_Factory(t) {
return new MyApp( return new (t || MyApp)(
$r3$.ɵdirectiveInject(ServiceA), $r3$.ɵdirectiveInject(ServiceB), inject(INJECTOR)); $r3$.ɵdirectiveInject(ServiceA), $r3$.ɵdirectiveInject(ServiceB), inject(INJECTOR));
}, },
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {}, template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {},
providers: [ServiceA], features: [ProvidersFeature([ServiceA], [ServiceB])]
viewProviders: [ServiceB],
}); });
} }
const e0_attrs = ['title', 'WORKS']; const e0_attrs = ['title', 'WORKS'];

View File

@ -45,7 +45,7 @@ describe('lifecycle hooks', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: LifecycleComp, type: LifecycleComp,
selectors: [['lifecycle-comp']], selectors: [['lifecycle-comp']],
factory: function LifecycleComp_Factory() { return new LifecycleComp(); }, factory: function LifecycleComp_Factory(t) { return new (t || LifecycleComp)(); },
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function LifecycleComp_Template(rf: $RenderFlags$, ctx: $LifecycleComp$) {}, template: function LifecycleComp_Template(rf: $RenderFlags$, ctx: $LifecycleComp$) {},
@ -70,7 +70,9 @@ describe('lifecycle hooks', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: SimpleLayout, type: SimpleLayout,
selectors: [['simple-layout']], selectors: [['simple-layout']],
factory: function SimpleLayout_Factory() { return simpleLayout = new SimpleLayout(); }, factory: function SimpleLayout_Factory(t) {
return simpleLayout = new (t || SimpleLayout)();
},
consts: 2, consts: 2,
vars: 2, vars: 2,
template: function SimpleLayout_Template(rf: $RenderFlags$, ctx: $SimpleLayout$) { template: function SimpleLayout_Template(rf: $RenderFlags$, ctx: $SimpleLayout$) {

View File

@ -27,7 +27,7 @@ describe('local references', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: () => new MyComponent, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 3, consts: 3,
vars: 1, vars: 1,
template: function(rf: $RenderFlags$, ctx: $MyComponent$) { template: function(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -64,7 +64,7 @@ describe('local references', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: () => new MyComponent, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 3, consts: 3,
vars: 1, vars: 1,
template: function(rf: $RenderFlags$, ctx: $MyComponent$) { template: function(rf: $RenderFlags$, ctx: $MyComponent$) {

View File

@ -34,7 +34,7 @@ xdescribe('NgModule', () => {
constructor(name: String) {} constructor(name: String) {}
// NORMATIVE // NORMATIVE
static ngInjectableDef = defineInjectable({ static ngInjectableDef = defineInjectable({
factory: () => new Toast($r3$.ɵdirectiveInject(String)), factory: function Toast_Factory() { return new Toast($r3$.ɵdirectiveInject(String)); },
}); });
// /NORMATIVE // /NORMATIVE
} }
@ -53,7 +53,7 @@ xdescribe('NgModule', () => {
constructor(toast: Toast) {} constructor(toast: Toast) {}
// NORMATIVE // NORMATIVE
static ngInjectorDef = defineInjector({ static ngInjectorDef = defineInjector({
factory: () => new MyModule($r3$.ɵdirectiveInject(Toast)), factory: function MyModule_Factory() { return new MyModule($r3$.ɵdirectiveInject(Toast)); },
provider: [ provider: [
{provide: Toast, deps: [String]}, // If Toast has metadata generate this line {provide: Toast, deps: [String]}, // If Toast has metadata generate this line
Toast, // If Toast has no metadata generate this line. Toast, // If Toast has no metadata generate this line.
@ -70,9 +70,11 @@ xdescribe('NgModule', () => {
// NORMATIVE // NORMATIVE
static ngInjectableDef = defineInjectable({ static ngInjectableDef = defineInjectable({
providedIn: MyModule, providedIn: MyModule,
factory: () => new BurntToast( factory: function BurntToast_Factory() {
$r3$.ɵdirectiveInject(Toast, $core$.InjectFlags.Optional), return new BurntToast(
$r3$.ɵdirectiveInject(String)), $r3$.ɵdirectiveInject(Toast, $core$.InjectFlags.Optional),
$r3$.ɵdirectiveInject(String));
},
}); });
// /NORMATIVE // /NORMATIVE
} }

View File

@ -43,7 +43,7 @@ describe('pipes', () => {
static ngPipeDef = $r3$.ɵdefinePipe({ static ngPipeDef = $r3$.ɵdefinePipe({
name: 'myPipe', name: 'myPipe',
type: MyPipe, type: MyPipe,
factory: function MyPipe_Factory() { return new MyPipe(); }, factory: function MyPipe_Factory(t) { return new (t || MyPipe)(); },
pure: false, pure: false,
}); });
// /NORMATIVE // /NORMATIVE
@ -63,7 +63,7 @@ describe('pipes', () => {
static ngPipeDef = $r3$.ɵdefinePipe({ static ngPipeDef = $r3$.ɵdefinePipe({
name: 'myPurePipe', name: 'myPurePipe',
type: MyPurePipe, type: MyPurePipe,
factory: function MyPurePipe_Factory() { return new MyPurePipe(); }, factory: function MyPurePipe_Factory(t) { return new (t || MyPurePipe)(); },
pure: true, pure: true,
}); });
// /NORMATIVE // /NORMATIVE
@ -83,7 +83,7 @@ describe('pipes', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 3, consts: 3,
vars: 7, vars: 7,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
@ -146,9 +146,11 @@ describe('pipes', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: OneTimeIf, type: OneTimeIf,
selectors: [['', 'oneTimeIf', '']], selectors: [['', 'oneTimeIf', '']],
factory: () => new OneTimeIf( factory: function OneTimeIf_Factory(t) {
$r3$.ɵdirectiveInject(ViewContainerRef as any), return new (t || OneTimeIf)(
$r3$.ɵdirectiveInject(TemplateRef as any)), $r3$.ɵdirectiveInject(ViewContainerRef as any),
$r3$.ɵdirectiveInject(TemplateRef as any));
},
inputs: {oneTimeIf: 'oneTimeIf'} inputs: {oneTimeIf: 'oneTimeIf'}
}); });
// /NORMATIVE // /NORMATIVE
@ -181,7 +183,7 @@ describe('pipes', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 5, consts: 5,
vars: 9, vars: 9,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {

View File

@ -25,8 +25,7 @@ describe('queries', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: SomeDirective, type: SomeDirective,
selectors: [['', 'someDir', '']], selectors: [['', 'someDir', '']],
factory: function SomeDirective_Factory() { return someDir = new SomeDirective(); }, factory: function SomeDirective_Factory(t) { return someDir = new (t || SomeDirective)(); }
features: [$r3$.ɵPublicFeature]
}); });
} }
@ -53,7 +52,7 @@ describe('queries', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: ViewQueryComponent, type: ViewQueryComponent,
selectors: [['view-query-component']], selectors: [['view-query-component']],
factory: function ViewQueryComponent_Factory() { return new ViewQueryComponent(); }, factory: function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); },
consts: 3, consts: 3,
vars: 0, vars: 0,
template: function ViewQueryComponent_Template( template: function ViewQueryComponent_Template(
@ -111,12 +110,14 @@ describe('queries', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: ContentQueryComponent, type: ContentQueryComponent,
selectors: [['content-query-component']], selectors: [['content-query-component']],
factory: function ContentQueryComponent_Factory() { return new ContentQueryComponent(); }, factory: function ContentQueryComponent_Factory(t) {
return new (t || ContentQueryComponent)();
},
consts: 2, consts: 2,
vars: 0, vars: 0,
contentQueries: function ContentQueryComponent_ContentQueries() { contentQueries: function ContentQueryComponent_ContentQueries(dirIndex: $number$) {
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false), dirIndex);
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false)); $r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false), dirIndex);
}, },
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh( contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(
dirIndex: $number$, queryStartIndex: $number$) { dirIndex: $number$, queryStartIndex: $number$) {
@ -155,7 +156,7 @@ describe('queries', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {

View File

@ -40,7 +40,7 @@ describe('compiler sanitization', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 2, consts: 2,
vars: 4, vars: 4,
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) { template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {

View File

@ -74,8 +74,8 @@ class ToDoAppComponent {
static ngComponentDef = r3.defineComponent({ static ngComponentDef = r3.defineComponent({
type: ToDoAppComponent, type: ToDoAppComponent,
selectors: [['todo-app']], selectors: [['todo-app']],
factory: function ToDoAppComponent_Factory() { factory: function ToDoAppComponent_Factory(t) {
return new ToDoAppComponent(r3.directiveInject(AppState)); return new (t || ToDoAppComponent)(r3.directiveInject(AppState));
}, },
consts: 6, consts: 6,
vars: 1, vars: 1,
@ -135,7 +135,7 @@ class ToDoItemComponent {
static ngComponentDef = r3.defineComponent({ static ngComponentDef = r3.defineComponent({
type: ToDoItemComponent, type: ToDoItemComponent,
selectors: [['todo']], selectors: [['todo']],
factory: function ToDoItemComponent_Factory() { return new ToDoItemComponent(); }, factory: function ToDoItemComponent_Factory(t) { return new (t || ToDoItemComponent)(); },
consts: 6, consts: 6,
vars: 2, vars: 2,
template: function ToDoItemComponent_Template(rf: $RenderFlags$, ctx: ToDoItemComponent) { template: function ToDoItemComponent_Template(rf: $RenderFlags$, ctx: ToDoItemComponent) {
@ -174,7 +174,7 @@ const e1_attrs = ['type', 'checkbox'];
class ToDoAppModule { class ToDoAppModule {
// NORMATIVE // NORMATIVE
static ngInjectorDef = defineInjector({ static ngInjectorDef = defineInjector({
factory: () => new ToDoAppModule(), factory: function ToDoAppModule_Factory() { return new ToDoAppModule(); },
providers: [AppState], providers: [AppState],
}); });
// /NORMATIVE // /NORMATIVE

View File

@ -69,8 +69,8 @@ describe('template variables', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: ForOfDirective, type: ForOfDirective,
selectors: [['', 'forOf', '']], selectors: [['', 'forOf', '']],
factory: function ForOfDirective_Factory() { factory: function ForOfDirective_Factory(t) {
return new ForOfDirective( return new (t || ForOfDirective)(
$r3$.ɵdirectiveInject(ViewContainerRef as any), $r3$.ɵdirectiveInject(ViewContainerRef as any),
$r3$.ɵdirectiveInject(TemplateRef as any)); $r3$.ɵdirectiveInject(TemplateRef as any));
}, },
@ -111,7 +111,7 @@ describe('template variables', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) { template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {
@ -205,7 +205,7 @@ describe('template variables', () => {
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-component']], selectors: [['my-component']],
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) { template: function MyComponent_Template(rf: $RenderFlags$, ctx: $MyComponent$) {

File diff suppressed because it is too large Load Diff

View File

@ -10,14 +10,15 @@ import {Attribute, ChangeDetectorRef, ElementRef, Host, InjectFlags, Injector, O
import {RenderFlags} from '@angular/core/src/render3/interfaces/definition'; import {RenderFlags} from '@angular/core/src/render3/interfaces/definition';
import {defineComponent} from '../../src/render3/definition'; import {defineComponent} from '../../src/render3/definition';
import {bloomAdd, bloomHashBitOrFactory as bloomHash, getOrCreateNodeInjector, injectAttribute, injectorHasToken} from '../../src/render3/di'; import {bloomAdd, bloomHasToken, bloomHashBitOrFactory as bloomHash, getOrCreateNodeInjectorForNode} from '../../src/render3/di';
import {PublicFeature, defineDirective, directiveInject, elementProperty, load, templateRefExtractor} from '../../src/render3/index'; import {defineDirective, elementProperty, load, templateRefExtractor} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, createNodeAtIndex, createLViewData, createTView, element, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, projection, projectionDef, reference, template, text, textBinding, elementContainerStart, elementContainerEnd, _getViewData} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, createNodeAtIndex, createLViewData, createTView, directiveInject, element, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, injectAttribute, interpolation2, projection, projectionDef, reference, template, text, textBinding, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
import {isProceduralRenderer, RElement} from '../../src/render3/interfaces/renderer'; import {isProceduralRenderer, RElement} from '../../src/render3/interfaces/renderer';
import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node'; import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node';
import {getNativeByIndex} from '../../src/render3/util'; import {getNativeByIndex} from '../../src/render3/util';
import {LViewFlags} from '../../src/render3/interfaces/view'; import {LViewFlags} from '../../src/render3/interfaces/view';
import {getViewData, enterView, leaveView} from '../../src/render3/state';
import {ViewRef} from '../../src/render3/view_ref'; import {ViewRef} from '../../src/render3/view_ref';
import {getRendererFactory2} from './imported_renderer2'; import {getRendererFactory2} from './imported_renderer2';
@ -68,7 +69,6 @@ describe('di', () => {
selectors: [['', 'dirB', '']], selectors: [['', 'dirB', '']],
type: DirB, type: DirB,
factory: () => new DirB(), factory: () => new DirB(),
features: [PublicFeature],
inputs: {value: 'value'} inputs: {value: 'value'}
}); });
} }
@ -78,12 +78,8 @@ describe('di', () => {
it('should create directive with intra view dependencies', () => { it('should create directive with intra view dependencies', () => {
class DirA { class DirA {
value: string = 'DirA'; value: string = 'DirA';
static ngDirectiveDef = defineDirective({ static ngDirectiveDef =
type: DirA, defineDirective({type: DirA, selectors: [['', 'dirA', '']], factory: () => new DirA()});
selectors: [['', 'dirA', '']],
factory: () => new DirA(),
features: [PublicFeature]
});
} }
class DirC { class DirC {
@ -246,12 +242,8 @@ describe('di', () => {
value = 'DirA'; value = 'DirA';
constructor() { log.push(this.value); } constructor() { log.push(this.value); }
static ngDirectiveDef = defineDirective({ static ngDirectiveDef =
selectors: [['', 'dirA', '']], defineDirective({selectors: [['', 'dirA', '']], type: DirA, factory: () => new DirA()});
type: DirA,
factory: () => new DirA(),
features: [PublicFeature]
});
} }
class DirB { class DirB {
@ -270,12 +262,8 @@ describe('di', () => {
value = 'DirC'; value = 'DirC';
constructor() { log.push(this.value); } constructor() { log.push(this.value); }
static ngDirectiveDef = defineDirective({ static ngDirectiveDef =
selectors: [['', 'dirC', '']], defineDirective({selectors: [['', 'dirC', '']], type: DirC, factory: () => new DirC()});
type: DirC,
factory: () => new DirC(),
features: [PublicFeature]
});
} }
/** <div dirA dirB dirC></div> */ /** <div dirA dirB dirC></div> */
@ -310,8 +298,7 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
selectors: [['', 'dirA', '']], selectors: [['', 'dirA', '']],
type: DirA, type: DirA,
factory: () => new DirA(directiveInject(DirC)), factory: () => new DirA(directiveInject(DirC))
features: [PublicFeature]
}); });
} }
@ -322,8 +309,7 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
selectors: [['', 'dirC', '']], selectors: [['', 'dirC', '']],
type: DirC, type: DirC,
factory: () => new DirC(directiveInject(DirB)), factory: () => new DirC(directiveInject(DirB))
features: [PublicFeature]
}); });
} }
@ -334,8 +320,7 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
selectors: [['', 'dirD', '']], selectors: [['', 'dirD', '']],
type: DirD, type: DirD,
factory: () => new DirD(directiveInject(DirA)), factory: () => new DirD(directiveInject(DirA))
features: [PublicFeature]
}); });
} }
@ -379,8 +364,7 @@ describe('di', () => {
element(0, 'div', ['dirA', '', 'dirB', '', 'dirC', 'dirC']); element(0, 'div', ['dirA', '', 'dirB', '', 'dirC', 'dirC']);
} }
}, },
directives: [DirA, DirB], directives: [DirA, DirB]
features: [PublicFeature],
}); });
} }
@ -409,12 +393,8 @@ describe('di', () => {
this.count = count++; this.count = count++;
} }
static ngDirectiveDef = defineDirective({ static ngDirectiveDef =
selectors: [['', 'dirB', '']], defineDirective({selectors: [['', 'dirB', '']], type: DirB, factory: () => new DirB()});
type: DirB,
factory: () => new DirB(),
features: [PublicFeature],
});
} }
/** <div dirA dirB></div> */ /** <div dirA dirB></div> */
@ -447,7 +427,6 @@ describe('di', () => {
type: DirA, type: DirA,
selectors: [['', 'dirA', '']], selectors: [['', 'dirA', '']],
factory: () => new DirA(directiveInject(DirB), directiveInject(ViewContainerRef as any)), factory: () => new DirA(directiveInject(DirB), directiveInject(ViewContainerRef as any)),
features: [PublicFeature],
exportAs: 'dirA' exportAs: 'dirA'
}); });
} }
@ -599,8 +578,7 @@ describe('di', () => {
selectors: [['', 'structuralDir', '']], selectors: [['', 'structuralDir', '']],
factory: () => structuralDir = factory: () => structuralDir =
new StructuralDir(directiveInject(ViewContainerRef as any)), new StructuralDir(directiveInject(ViewContainerRef as any)),
inputs: {tmp: 'tmp'}, inputs: {tmp: 'tmp'}
features: [PublicFeature]
}); });
} }
@ -763,18 +741,13 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
type: Dir, type: Dir,
factory: () => new Dir(directiveInject(OtherDir)), factory: () => new Dir(directiveInject(OtherDir))
features: [PublicFeature]
}); });
} }
class OtherDir { class OtherDir {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective(
selectors: [['', 'other', '']], {selectors: [['', 'other', '']], type: OtherDir, factory: () => new OtherDir()});
type: OtherDir,
factory: () => new OtherDir(),
features: [PublicFeature]
});
} }
/** <div dir></div> */ /** <div dir></div> */
@ -794,18 +767,13 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
type: Dir, type: Dir,
factory: () => new Dir(directiveInject(OtherDir)), factory: () => new Dir(directiveInject(OtherDir))
features: [PublicFeature]
}); });
} }
class OtherDir { class OtherDir {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective(
selectors: [['', 'other', '']], {selectors: [['', 'other', '']], type: OtherDir, factory: () => new OtherDir()});
type: OtherDir,
factory: () => new OtherDir(),
features: [PublicFeature]
});
} }
/** /**
@ -830,8 +798,7 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
selectors: [['', 'dirA', '']], selectors: [['', 'dirA', '']],
type: DirA, type: DirA,
factory: () => new DirA(directiveInject(DirB)), factory: () => new DirA(directiveInject(DirB))
features: [PublicFeature]
}); });
} }
@ -841,8 +808,7 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
selectors: [['', 'dirB', '']], selectors: [['', 'dirB', '']],
type: DirB, type: DirB,
factory: () => new DirB(directiveInject(DirA)), factory: () => new DirB(directiveInject(DirA))
features: [PublicFeature]
}); });
} }
@ -853,7 +819,7 @@ describe('di', () => {
} }
}, 1, 0, [DirA, DirB]); }, 1, 0, [DirA, DirB]);
expect(() => new ComponentFixture(App)).toThrowError(/Cannot instantiate cyclic dependency!/); expect(() => new ComponentFixture(App)).toThrowError(/Circular dep for/);
}); });
it('should throw if directive tries to inject itself', () => { it('should throw if directive tries to inject itself', () => {
@ -863,8 +829,7 @@ describe('di', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
type: Dir, type: Dir,
factory: () => new Dir(directiveInject(Dir)), factory: () => new Dir(directiveInject(Dir))
features: [PublicFeature]
}); });
} }
@ -875,7 +840,7 @@ describe('di', () => {
} }
}, 1, 0, [Dir]); }, 1, 0, [Dir]);
expect(() => new ComponentFixture(App)).toThrowError(/Cannot instantiate cyclic dependency!/); expect(() => new ComponentFixture(App)).toThrowError(/Circular dep for/);
}); });
describe('flags', () => { describe('flags', () => {
@ -888,8 +853,7 @@ describe('di', () => {
type: DirB, type: DirB,
selectors: [['', 'dirB', '']], selectors: [['', 'dirB', '']],
factory: () => new DirB(), factory: () => new DirB(),
inputs: {value: 'dirB'}, inputs: {value: 'dirB'}
features: [PublicFeature]
}); });
} }
@ -1006,7 +970,9 @@ describe('di', () => {
} }
}, 2, 0, [DirA, DirB]); }, 2, 0, [DirA, DirB]);
expect(() => { new ComponentFixture(App); }).toThrowError(/Injector: NOT_FOUND \[DirB\]/); expect(() => {
new ComponentFixture(App);
}).toThrowError(/NodeInjector: NOT_FOUND \[DirB\]/);
}); });
it('should check only the current node with @Self even with false positive', () => { it('should check only the current node with @Self even with false positive', () => {
@ -1041,7 +1007,7 @@ describe('di', () => {
(DirA as any)['__NG_ELEMENT_ID__'] = 1; (DirA as any)['__NG_ELEMENT_ID__'] = 1;
(DirC as any)['__NG_ELEMENT_ID__'] = 257; (DirC as any)['__NG_ELEMENT_ID__'] = 257;
new ComponentFixture(App); new ComponentFixture(App);
}).toThrowError(/Injector: NOT_FOUND \[DirB\]/); }).toThrowError(/NodeInjector: NOT_FOUND \[DirB\]/);
}); });
it('should not pass component boundary with @Host', () => { it('should not pass component boundary with @Host', () => {
@ -1071,7 +1037,9 @@ describe('di', () => {
} }
}, 1, 0, [Comp, DirB]); }, 1, 0, [Comp, DirB]);
expect(() => { new ComponentFixture(App); }).toThrowError(/Injector: NOT_FOUND \[DirB\]/); expect(() => {
new ComponentFixture(App);
}).toThrowError(/NodeInjector: NOT_FOUND \[DirB\]/);
}); });
@ -1097,7 +1065,6 @@ describe('di', () => {
type: Directive, type: Directive,
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
factory: () => dir = new Directive(directiveInject(ElementRef)), factory: () => dir = new Directive(directiveInject(ElementRef)),
features: [PublicFeature],
exportAs: 'dir' exportAs: 'dir'
}); });
} }
@ -1121,7 +1088,7 @@ describe('di', () => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', '']); elementStart(0, 'div', ['dir', '', 'dirSame', '']);
elementEnd(); elementEnd();
div = getNativeByIndex(0, _getViewData()); div = getNativeByIndex(0, getViewData());
} }
}, 1, 0, [Directive, DirectiveSameInstance]); }, 1, 0, [Directive, DirectiveSameInstance]);
@ -1148,7 +1115,6 @@ describe('di', () => {
type: Directive, type: Directive,
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
factory: () => dir = new Directive(directiveInject(ElementRef)), factory: () => dir = new Directive(directiveInject(ElementRef)),
features: [PublicFeature],
exportAs: 'dir' exportAs: 'dir'
}); });
} }
@ -1179,7 +1145,6 @@ describe('di', () => {
type: Directive, type: Directive,
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
factory: () => new Directive(directiveInject(TemplateRef as any)), factory: () => new Directive(directiveInject(TemplateRef as any)),
features: [PublicFeature],
exportAs: 'dir' exportAs: 'dir'
}); });
} }
@ -1234,7 +1199,6 @@ describe('di', () => {
type: Directive, type: Directive,
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
factory: () => new Directive(directiveInject(ViewContainerRef as any)), factory: () => new Directive(directiveInject(ViewContainerRef as any)),
features: [PublicFeature],
exportAs: 'dir' exportAs: 'dir'
}); });
} }
@ -1298,8 +1262,7 @@ describe('di', () => {
projectionDef(); projectionDef();
projection(0); projection(0);
} }
}, }
features: [PublicFeature]
}); });
} }
@ -1312,7 +1275,6 @@ describe('di', () => {
type: Directive, type: Directive,
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
factory: () => dir = new Directive(directiveInject(ChangeDetectorRef as any)), factory: () => dir = new Directive(directiveInject(ChangeDetectorRef as any)),
features: [PublicFeature],
exportAs: 'dir' exportAs: 'dir'
}); });
} }
@ -1324,8 +1286,7 @@ describe('di', () => {
type: DirectiveSameInstance, type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']], selectors: [['', 'dirSame', '']],
factory: () => dirSameInstance = factory: () => dirSameInstance =
new DirectiveSameInstance(directiveInject(ChangeDetectorRef as any)), new DirectiveSameInstance(directiveInject(ChangeDetectorRef as any))
features: [PublicFeature]
}); });
} }
@ -1421,8 +1382,7 @@ describe('di', () => {
textBinding(3, bind(tmp.value)); textBinding(3, bind(tmp.value));
} }
}, },
directives: directives, directives: directives
features: [PublicFeature]
}); });
} }
@ -1749,15 +1709,15 @@ describe('di', () => {
bloomAdd(0, mockTView, Dir198); bloomAdd(0, mockTView, Dir198);
bloomAdd(0, mockTView, Dir231); bloomAdd(0, mockTView, Dir231);
expect(injectorHasToken(bloomHash(Dir0) as number, 0, mockTView.data)).toEqual(true); expect(bloomHasToken(bloomHash(Dir0) as number, 0, mockTView.data)).toEqual(true);
expect(injectorHasToken(bloomHash(Dir1) as number, 0, mockTView.data)).toEqual(false); expect(bloomHasToken(bloomHash(Dir1) as number, 0, mockTView.data)).toEqual(false);
expect(injectorHasToken(bloomHash(Dir33) as number, 0, mockTView.data)).toEqual(true); expect(bloomHasToken(bloomHash(Dir33) as number, 0, mockTView.data)).toEqual(true);
expect(injectorHasToken(bloomHash(Dir66) as number, 0, mockTView.data)).toEqual(true); expect(bloomHasToken(bloomHash(Dir66) as number, 0, mockTView.data)).toEqual(true);
expect(injectorHasToken(bloomHash(Dir99) as number, 0, mockTView.data)).toEqual(true); expect(bloomHasToken(bloomHash(Dir99) as number, 0, mockTView.data)).toEqual(true);
expect(injectorHasToken(bloomHash(Dir132) as number, 0, mockTView.data)).toEqual(true); expect(bloomHasToken(bloomHash(Dir132) as number, 0, mockTView.data)).toEqual(true);
expect(injectorHasToken(bloomHash(Dir165) as number, 0, mockTView.data)).toEqual(true); expect(bloomHasToken(bloomHash(Dir165) as number, 0, mockTView.data)).toEqual(true);
expect(injectorHasToken(bloomHash(Dir198) as number, 0, mockTView.data)).toEqual(true); expect(bloomHasToken(bloomHash(Dir198) as number, 0, mockTView.data)).toEqual(true);
expect(injectorHasToken(bloomHash(Dir231) as number, 0, mockTView.data)).toEqual(true); expect(bloomHasToken(bloomHash(Dir231) as number, 0, mockTView.data)).toEqual(true);
}); });
}); });
@ -1771,7 +1731,6 @@ describe('di', () => {
type: ChildDirective, type: ChildDirective,
selectors: [['', 'childDir', '']], selectors: [['', 'childDir', '']],
factory: () => new ChildDirective(directiveInject(ParentDirective)), factory: () => new ChildDirective(directiveInject(ParentDirective)),
features: [PublicFeature],
exportAs: 'childDir' exportAs: 'childDir'
}); });
} }
@ -1847,7 +1806,7 @@ describe('di', () => {
// so that we have smaller HelloWorld. // so that we have smaller HelloWorld.
(parentTNode as{parent: any}).parent = undefined; (parentTNode as{parent: any}).parent = undefined;
const injector: any = getOrCreateNodeInjector(); // TODO: Review use of `any` here (#19904) const injector = getOrCreateNodeInjectorForNode(parentTNode, contentView);
expect(injector).not.toEqual(-1); expect(injector).not.toEqual(-1);
} finally { } finally {
leaveView(oldView); leaveView(oldView);

View File

@ -7,7 +7,7 @@
*/ */
import {StaticInjector} from '../../src/di/injector'; import {StaticInjector} from '../../src/di/injector';
import {getComponent, getDirectives, getHostComponent, getInjector, getLocalRefs, getRootComponents} from '../../src/render3/discovery_utils'; import {getComponent, getDirectives, getHostComponent, getInjector, getLocalRefs, getRootComponents} from '../../src/render3/discovery_utils';
import {PublicFeature, RenderFlags, defineComponent, defineDirective} from '../../src/render3/index'; import {RenderFlags, defineComponent, defineDirective} from '../../src/render3/index';
import {element, elementEnd, elementStart, elementStyling, elementStylingApply} from '../../src/render3/instructions'; import {element, elementEnd, elementStart, elementStyling, elementStylingApply} from '../../src/render3/instructions';
import {ComponentFixture} from './render_util'; import {ComponentFixture} from './render_util';
@ -231,8 +231,7 @@ describe('discovery utils', () => {
factory: () => new Comp(), factory: () => new Comp(),
consts: 0, consts: 0,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: Comp) => {}, template: (rf: RenderFlags, ctx: Comp) => {}
features: [PublicFeature]
}); });
} }
@ -252,8 +251,7 @@ describe('discovery utils', () => {
factory: () => new Comp(), factory: () => new Comp(),
consts: 0, consts: 0,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: Comp) => {}, template: (rf: RenderFlags, ctx: Comp) => {}
features: [PublicFeature]
}); });
} }

View File

@ -10,11 +10,12 @@ import {ElementRef, TemplateRef, ViewContainerRef} from '@angular/core';
import {RendererStyleFlags2, RendererType2} from '../../src/render/api'; import {RendererStyleFlags2, RendererType2} from '../../src/render/api';
import {AttributeMarker, defineComponent, defineDirective, templateRefExtractor} from '../../src/render3/index'; import {AttributeMarker, defineComponent, defineDirective, templateRefExtractor} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementAttribute, elementClassProp, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, elementStyleProp, elementStyling, elementStylingApply, embeddedViewEnd, embeddedViewStart, enableBindings, disableBindings, interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV, load, projection, projectionDef, reference, text, textBinding, template, elementStylingMap} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementAttribute, elementClassProp, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, elementStyleProp, elementStyling, elementStylingApply, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV, load, projection, projectionDef, reference, text, textBinding, template, elementStylingMap, directiveInject} from '../../src/render3/instructions';
import {InitialStylingFlags, RenderFlags} from '../../src/render3/interfaces/definition'; import {InitialStylingFlags, RenderFlags} from '../../src/render3/interfaces/definition';
import {RElement, Renderer3, RendererFactory3, domRendererFactory3, RText, RComment, RNode, RendererStyleFlags3, ProceduralRenderer3} from '../../src/render3/interfaces/renderer'; import {RElement, Renderer3, RendererFactory3, domRendererFactory3, RText, RComment, RNode, RendererStyleFlags3, ProceduralRenderer3} from '../../src/render3/interfaces/renderer';
import {NO_CHANGE} from '../../src/render3/tokens'; import {NO_CHANGE} from '../../src/render3/tokens';
import {HEADER_OFFSET, CONTEXT} from '../../src/render3/interfaces/view'; import {HEADER_OFFSET, CONTEXT} from '../../src/render3/interfaces/view';
import {enableBindings, disableBindings} from '../../src/render3/state';
import {sanitizeUrl} from '../../src/sanitization/sanitization'; import {sanitizeUrl} from '../../src/sanitization/sanitization';
import {Sanitizer, SecurityContext} from '../../src/sanitization/security'; import {Sanitizer, SecurityContext} from '../../src/sanitization/security';
@ -23,7 +24,6 @@ import {ComponentFixture, TemplateFixture, createComponent, renderToHtml} from '
import {getContext} from '../../src/render3/context_discovery'; import {getContext} from '../../src/render3/context_discovery';
import {StylingIndex} from '../../src/render3/interfaces/styling'; import {StylingIndex} from '../../src/render3/interfaces/styling';
import {MONKEY_PATCH_KEY_NAME} from '../../src/render3/interfaces/context'; import {MONKEY_PATCH_KEY_NAME} from '../../src/render3/interfaces/context';
import {directiveInject} from '../../src/render3/di';
describe('render3 integration test', () => { describe('render3 integration test', () => {

View File

@ -239,7 +239,7 @@ ivyEnabled && describe('render3 jit', () => {
const pipeDef = (P as any).ngPipeDef as PipeDef<P>; const pipeDef = (P as any).ngPipeDef as PipeDef<P>;
expect(pipeDef.name).toBe('test-pipe'); expect(pipeDef.name).toBe('test-pipe');
expect(pipeDef.pure).toBe(false, 'pipe should not be pure'); expect(pipeDef.pure).toBe(false, 'pipe should not be pure');
expect(pipeDef.factory() instanceof P) expect(pipeDef.factory(null) instanceof P)
.toBe(true, 'factory() should create an instance of the pipe'); .toBe(true, 'factory() should create an instance of the pipe');
}); });

View File

@ -36,7 +36,7 @@ describe('NgOnChangesFeature', () => {
} }
const myDir = const myDir =
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).factory() as MyDirective; (MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).factory(null) as MyDirective;
myDir.valA = 'first'; myDir.valA = 'first';
expect(myDir.valA).toEqual('first'); expect(myDir.valA).toEqual('first');
myDir.valB = 'second'; myDir.valB = 'second';
@ -89,7 +89,7 @@ describe('NgOnChangesFeature', () => {
} }
const myDir = const myDir =
(SubDirective.ngDirectiveDef as DirectiveDef<SubDirective>).factory() as SubDirective; (SubDirective.ngDirectiveDef as DirectiveDef<SubDirective>).factory(null) as SubDirective;
myDir.valA = 'first'; myDir.valA = 'first';
expect(myDir.valA).toEqual('first'); expect(myDir.valA).toEqual('first');
@ -142,7 +142,7 @@ describe('NgOnChangesFeature', () => {
} }
const myDir = const myDir =
(SubDirective.ngDirectiveDef as DirectiveDef<SubDirective>).factory() as SubDirective; (SubDirective.ngDirectiveDef as DirectiveDef<SubDirective>).factory(null) as SubDirective;
myDir.valA = 'first'; myDir.valA = 'first';
myDir.valB = 'second'; myDir.valB = 'second';
@ -183,7 +183,7 @@ describe('NgOnChangesFeature', () => {
} }
const myDir = const myDir =
(SubDirective.ngDirectiveDef as DirectiveDef<SubDirective>).factory() as SubDirective; (SubDirective.ngDirectiveDef as DirectiveDef<SubDirective>).factory(null) as SubDirective;
myDir.valA = 'first'; myDir.valA = 'first';
myDir.valB = 'second'; myDir.valB = 'second';
@ -237,7 +237,7 @@ describe('NgOnChangesFeature', () => {
} }
const myDir = const myDir =
(SubDirective.ngDirectiveDef as DirectiveDef<SubDirective>).factory() as SubDirective; (SubDirective.ngDirectiveDef as DirectiveDef<SubDirective>).factory(null) as SubDirective;
myDir.valA = 'first'; myDir.valA = 'first';
expect(myDir.valA).toEqual('first'); expect(myDir.valA).toEqual('first');
@ -279,7 +279,7 @@ describe('NgOnChangesFeature', () => {
} }
const myDir = const myDir =
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).factory() as MyDirective; (MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).factory(null) as MyDirective;
myDir.valA = 'first'; myDir.valA = 'first';
myDir.valB = 'second'; myDir.valB = 'second';
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).doCheck !.call(myDir); (MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).doCheck !.call(myDir);
@ -315,7 +315,7 @@ describe('NgOnChangesFeature', () => {
} }
const myDir = const myDir =
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).factory() as MyDirective; (MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).factory(null) as MyDirective;
myDir.onlySetter = 'someValue'; myDir.onlySetter = 'someValue';
expect(myDir.onlySetter).toBeUndefined(); expect(myDir.onlySetter).toBeUndefined();
(MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).doCheck !.call(myDir); (MyDirective.ngDirectiveDef as DirectiveDef<MyDirective>).doCheck !.call(myDir);

View File

@ -11,15 +11,16 @@ import {AttributeMarker, TAttributes, TNode, TNodeType} from '../../src/render3/
import {CssSelector, CssSelectorList, NG_PROJECT_AS_ATTR_NAME, SelectorFlags,} from '../../src/render3/interfaces/projection'; import {CssSelector, CssSelectorList, NG_PROJECT_AS_ATTR_NAME, SelectorFlags,} from '../../src/render3/interfaces/projection';
import {getProjectAsAttrValue, isNodeMatchingSelectorList, isNodeMatchingSelector} from '../../src/render3/node_selector_matcher'; import {getProjectAsAttrValue, isNodeMatchingSelectorList, isNodeMatchingSelector} from '../../src/render3/node_selector_matcher';
import {createTNode} from '@angular/core/src/render3/instructions'; import {createTNode} from '@angular/core/src/render3/instructions';
import {getViewData} from '@angular/core/src/render3/state';
function testLStaticData(tagName: string, attrs: TAttributes | null): TNode { function testLStaticData(tagName: string, attrs: TAttributes | null): TNode {
return createTNode(TNodeType.Element, 0, tagName, attrs, null); return createTNode(getViewData(), TNodeType.Element, 0, tagName, attrs, null);
} }
describe('css selector matching', () => { describe('css selector matching', () => {
function isMatching(tagName: string, attrs: TAttributes | null, selector: CssSelector): boolean { function isMatching(tagName: string, attrs: TAttributes | null, selector: CssSelector): boolean {
return isNodeMatchingSelector( return isNodeMatchingSelector(
createTNode(TNodeType.Element, 0, tagName, attrs, null), selector); createTNode(getViewData(), TNodeType.Element, 0, tagName, attrs, null), selector);
} }
describe('isNodeMatchingSimpleSelector', () => { describe('isNodeMatchingSimpleSelector', () => {

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Directive, InjectionToken, OnChanges, OnDestroy, Pipe, PipeTransform, createInjector, defineInjectable, defineInjector, ɵNgModuleDef as NgModuleDef, ɵPublicFeature as PublicFeature, ɵdefineComponent as defineComponent, ɵdirectiveInject as directiveInject} from '@angular/core'; import {Directive, InjectionToken, OnChanges, OnDestroy, Pipe, PipeTransform, createInjector, defineInjectable, defineInjector, ɵNgModuleDef as NgModuleDef, ɵdefineComponent as defineComponent, ɵdirectiveInject as directiveInject} from '@angular/core';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {defineDirective, definePipe} from '../../src/render3/definition'; import {defineDirective, definePipe} from '../../src/render3/definition';
@ -367,7 +367,6 @@ describe('pipe', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-app']], selectors: [['my-app']],
features: [PublicFeature],
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory() { return new MyComponent(); },
consts: 2, consts: 2,
vars: 3, vars: 3,

View File

@ -8,7 +8,7 @@
import {EventEmitter} from '@angular/core'; import {EventEmitter} from '@angular/core';
import {AttributeMarker, PublicFeature, defineComponent, template, defineDirective} from '../../src/render3/index'; import {AttributeMarker, defineComponent, template, defineDirective} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, listener, load, reference, text, textBinding} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, listener, load, reference, text, textBinding} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition'; import {RenderFlags} from '../../src/render3/interfaces/definition';
import {NO_CHANGE} from '../../src/render3/tokens'; import {NO_CHANGE} from '../../src/render3/tokens';
@ -168,8 +168,7 @@ describe('elementProperty', () => {
hostVars: 1, hostVars: 1,
hostBindings: (directiveIndex: number, elementIndex: number) => { hostBindings: (directiveIndex: number, elementIndex: number) => {
elementProperty(elementIndex, 'id', bind(load<HostBindingDir>(directiveIndex).id)); elementProperty(elementIndex, 'id', bind(load<HostBindingDir>(directiveIndex).id));
}, }
features: [PublicFeature]
}); });
} }
@ -190,8 +189,7 @@ describe('elementProperty', () => {
const ctx = load(dirIndex) as HostBindingComp; const ctx = load(dirIndex) as HostBindingComp;
elementProperty(elIndex, 'title', bind(ctx.title)); elementProperty(elIndex, 'title', bind(ctx.title));
}, },
template: (rf: RenderFlags, ctx: HostBindingComp) => {}, template: (rf: RenderFlags, ctx: HostBindingComp) => {}
features: [PublicFeature]
}); });
} }
@ -231,8 +229,7 @@ describe('elementProperty', () => {
hostVars: 1, hostVars: 1,
hostBindings: (directiveIndex: number, elementIndex: number) => { hostBindings: (directiveIndex: number, elementIndex: number) => {
elementProperty(elementIndex, 'id', bind(load<HostBindingDir>(directiveIndex).id)); elementProperty(elementIndex, 'id', bind(load<HostBindingDir>(directiveIndex).id));
}, }
features: [PublicFeature]
}); });
} }
@ -272,8 +269,7 @@ describe('elementProperty', () => {
hostVars: 1, hostVars: 1,
hostBindings: (directiveIndex: number, elementIndex: number) => { hostBindings: (directiveIndex: number, elementIndex: number) => {
elementProperty(elementIndex, 'id', bind(load<HostBindingDir>(directiveIndex).id)); elementProperty(elementIndex, 'id', bind(load<HostBindingDir>(directiveIndex).id));
}, }
features: [PublicFeature]
}); });
} }

View File

@ -10,13 +10,13 @@ import {NgForOfContext} from '@angular/common';
import {ElementRef, TemplateRef, ViewContainerRef} from '@angular/core'; import {ElementRef, TemplateRef, ViewContainerRef} from '@angular/core';
import {EventEmitter} from '../..'; import {EventEmitter} from '../..';
import {directiveInject} from '../../src/render3/di';
import {AttributeMarker, QueryList, defineComponent, defineDirective, detectChanges} from '../../src/render3/index'; import {AttributeMarker, QueryList, defineComponent, defineDirective, detectChanges} from '../../src/render3/index';
import {getNativeByIndex} from '../../src/render3/util'; import {getNativeByIndex} from '../../src/render3/util';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadQueryList, reference, registerContentQuery, template, _getViewData} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, directiveInject, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadQueryList, reference, registerContentQuery, template} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition'; import {RenderFlags} from '../../src/render3/interfaces/definition';
import {query, queryRefresh} from '../../src/render3/query'; import {query, queryRefresh} from '../../src/render3/query';
import {getViewData} from '../../src/render3/state';
import {templateRefExtractor} from '../../src/render3/view_engine_compatibility_prebound'; import {templateRefExtractor} from '../../src/render3/view_engine_compatibility_prebound';
import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def'; import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def';
@ -115,7 +115,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
element(1, 'div', ['child', '']); element(1, 'div', ['child', '']);
elToQuery = getNativeByIndex(1, _getViewData()); elToQuery = getNativeByIndex(1, getViewData());
} }
}, },
2, 0, [Child], [], 2, 0, [Child], [],
@ -222,7 +222,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
element(1, 'div', null, ['foo', '']); element(1, 'div', null, ['foo', '']);
elToQuery = getNativeByIndex(1, _getViewData()); elToQuery = getNativeByIndex(1, getViewData());
element(3, 'div'); element(3, 'div');
} }
}, },
@ -259,7 +259,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
element(2, 'div', null, ['foo', '', 'bar', '']); element(2, 'div', null, ['foo', '', 'bar', '']);
elToQuery = getNativeByIndex(2, _getViewData()); elToQuery = getNativeByIndex(2, getViewData());
element(5, 'div'); element(5, 'div');
} }
}, },
@ -306,10 +306,10 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
element(1, 'div', null, ['foo', '']); element(1, 'div', null, ['foo', '']);
el1ToQuery = getNativeByIndex(1, _getViewData()); el1ToQuery = getNativeByIndex(1, getViewData());
element(3, 'div'); element(3, 'div');
element(4, 'div', null, ['bar', '']); element(4, 'div', null, ['bar', '']);
el2ToQuery = getNativeByIndex(4, _getViewData()); el2ToQuery = getNativeByIndex(4, getViewData());
} }
}, },
6, 0, [], [], 6, 0, [], [],
@ -345,7 +345,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
element(1, 'div', null, ['foo', '']); element(1, 'div', null, ['foo', '']);
elToQuery = getNativeByIndex(1, _getViewData()); elToQuery = getNativeByIndex(1, getViewData());
element(3, 'div'); element(3, 'div');
} }
}, },
@ -381,7 +381,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
elementContainerStart(1, null, ['foo', '']); elementContainerStart(1, null, ['foo', '']);
elToQuery = getNativeByIndex(1, _getViewData()); elToQuery = getNativeByIndex(1, getViewData());
elementContainerEnd(); elementContainerEnd();
} }
}, },
@ -417,7 +417,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
elementContainerStart(1, null, ['foo', '']); elementContainerStart(1, null, ['foo', '']);
elToQuery = getNativeByIndex(1, _getViewData()); elToQuery = getNativeByIndex(1, getViewData());
elementContainerEnd(); elementContainerEnd();
} }
}, },
@ -480,7 +480,7 @@ describe('query', () => {
elementContainerStart(2); elementContainerStart(2);
{ {
element(3, 'div', null, ['foo', '']); element(3, 'div', null, ['foo', '']);
elToQuery = getNativeByIndex(3, _getViewData()); elToQuery = getNativeByIndex(3, getViewData());
} }
elementContainerEnd(); elementContainerEnd();
} }
@ -890,7 +890,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
element(1, 'div', ['child', ''], ['foo', 'child']); element(1, 'div', ['child', ''], ['foo', 'child']);
div = getNativeByIndex(1, _getViewData()); div = getNativeByIndex(1, getViewData());
} }
}, },
3, 0, [Child], [], 3, 0, [Child], [],
@ -925,7 +925,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
element(1, 'div', ['child', ''], ['foo', '', 'bar', 'child']); element(1, 'div', ['child', ''], ['foo', '', 'bar', 'child']);
div = getNativeByIndex(1, _getViewData()); div = getNativeByIndex(1, getViewData());
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
childInstance = getDirectiveOnNode(1); childInstance = getDirectiveOnNode(1);
@ -1409,7 +1409,7 @@ describe('query', () => {
{ {
if (rf1 & RenderFlags.Create) { if (rf1 & RenderFlags.Create) {
element(0, 'div', null, ['foo', '']); element(0, 'div', null, ['foo', '']);
firstEl = getNativeByIndex(0, _getViewData()); firstEl = getNativeByIndex(0, getViewData());
} }
} }
embeddedViewEnd(); embeddedViewEnd();
@ -1461,10 +1461,10 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
element(1, 'span', null, ['foo', '']); element(1, 'span', null, ['foo', '']);
firstEl = getNativeByIndex(1, _getViewData()); firstEl = getNativeByIndex(1, getViewData());
container(3); container(3);
element(4, 'span', null, ['foo', '']); element(4, 'span', null, ['foo', '']);
lastEl = getNativeByIndex(4, _getViewData()); lastEl = getNativeByIndex(4, getViewData());
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
containerRefreshStart(3); containerRefreshStart(3);
@ -1474,7 +1474,7 @@ describe('query', () => {
{ {
if (rf1 & RenderFlags.Create) { if (rf1 & RenderFlags.Create) {
element(0, 'div', null, ['foo', '']); element(0, 'div', null, ['foo', '']);
viewEl = getNativeByIndex(0, _getViewData()); viewEl = getNativeByIndex(0, getViewData());
} }
} }
embeddedViewEnd(); embeddedViewEnd();
@ -1541,7 +1541,7 @@ describe('query', () => {
{ {
if (rf0 & RenderFlags.Create) { if (rf0 & RenderFlags.Create) {
element(0, 'div', null, ['foo', '']); element(0, 'div', null, ['foo', '']);
firstEl = getNativeByIndex(0, _getViewData()); firstEl = getNativeByIndex(0, getViewData());
} }
} }
embeddedViewEnd(); embeddedViewEnd();
@ -1551,7 +1551,7 @@ describe('query', () => {
{ {
if (rf1 & RenderFlags.Create) { if (rf1 & RenderFlags.Create) {
element(0, 'span', null, ['foo', '']); element(0, 'span', null, ['foo', '']);
lastEl = getNativeByIndex(0, _getViewData()); lastEl = getNativeByIndex(0, getViewData());
} }
} }
embeddedViewEnd(); embeddedViewEnd();
@ -1614,7 +1614,7 @@ describe('query', () => {
{ {
if (rf0 & RenderFlags.Create) { if (rf0 & RenderFlags.Create) {
element(0, 'div', null, ['foo', '']); element(0, 'div', null, ['foo', '']);
firstEl = getNativeByIndex(0, _getViewData()); firstEl = getNativeByIndex(0, getViewData());
container(2); container(2);
} }
if (rf0 & RenderFlags.Update) { if (rf0 & RenderFlags.Update) {
@ -1625,7 +1625,7 @@ describe('query', () => {
{ {
if (rf2) { if (rf2) {
element(0, 'span', null, ['foo', '']); element(0, 'span', null, ['foo', '']);
lastEl = getNativeByIndex(0, _getViewData()); lastEl = getNativeByIndex(0, getViewData());
} }
} }
embeddedViewEnd(); embeddedViewEnd();
@ -1911,7 +1911,8 @@ describe('query', () => {
type: WithContentDirective, type: WithContentDirective,
selectors: [['', 'with-content', '']], selectors: [['', 'with-content', '']],
factory: () => new WithContentDirective(), factory: () => new WithContentDirective(),
contentQueries: () => { registerContentQuery(query(null, ['foo'], true)); }, contentQueries:
(dirIndex) => { registerContentQuery(query(null, ['foo'], true), dirIndex); },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
withContentInstance = load<WithContentDirective>(dirIndex); withContentInstance = load<WithContentDirective>(dirIndex);
@ -1932,7 +1933,8 @@ describe('query', () => {
template: function(rf: RenderFlags, ctx: any) {}, template: function(rf: RenderFlags, ctx: any) {},
consts: 0, consts: 0,
vars: 0, vars: 0,
contentQueries: () => { registerContentQuery(query(null, ['foo'], false)); }, contentQueries:
(dirIndex) => { registerContentQuery(query(null, ['foo'], false), dirIndex); },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
shallowCompInstance = load<ShallowComp>(dirIndex); shallowCompInstance = load<ShallowComp>(dirIndex);
@ -1971,6 +1973,51 @@ describe('query', () => {
`Expected content query results to be available when ngAfterContentChecked was called.`); `Expected content query results to be available when ngAfterContentChecked was called.`);
}); });
it('should support content queries for directives within repeated embedded views', () => {
/**
* % for (let i = 0; i < 3; i++) {
* <div with-content>
* <span #foo></span>
* </div>
* % }
*/
const AppComponent = createComponent('app-component', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
container(0);
}
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
for (let i = 0; i < 3; i++) {
let rf = embeddedViewStart(1, 3, 0);
if (rf & RenderFlags.Create) {
elementStart(0, 'div', [AttributeMarker.SelectOnly, 'with-content']);
{ element(1, 'span', null, ['foo', '']); }
elementEnd();
}
embeddedViewEnd();
}
}
containerRefreshEnd();
}
}, 1, 0, [WithContentDirective]);
const fixture = new ComponentFixture(AppComponent);
expect(withContentInstance !.foos.length)
.toBe(1, `Expected content query to match <span #foo>.`);
expect(withContentInstance !.contentInitQuerySnapshot)
.toBe(
1,
`Expected content query results to be available when ngAfterContentInit was called.`);
expect(withContentInstance !.contentCheckedQuerySnapshot)
.toBe(
1,
`Expected content query results to be available when ngAfterContentChecked was called.`);
});
it('should support content query matches on directive hosts', () => { it('should support content query matches on directive hosts', () => {
/** /**
* <div with-content #foo> * <div with-content #foo>
@ -2109,10 +2156,10 @@ describe('query', () => {
selectors: [['', 'query', '']], selectors: [['', 'query', '']],
exportAs: 'query', exportAs: 'query',
factory: () => new QueryDirective(), factory: () => new QueryDirective(),
contentQueries: () => { contentQueries: (dirIndex) => {
// @ContentChildren('foo, bar, baz', {descendants: true}) fooBars: // @ContentChildren('foo, bar, baz', {descendants: true}) fooBars:
// QueryList<ElementRef>; // QueryList<ElementRef>;
registerContentQuery(query(null, ['foo', 'bar', 'baz'], true)); registerContentQuery(query(null, ['foo', 'bar', 'baz'], true), dirIndex);
}, },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
@ -2173,10 +2220,10 @@ describe('query', () => {
selectors: [['', 'query', '']], selectors: [['', 'query', '']],
exportAs: 'query', exportAs: 'query',
factory: () => new QueryDirective(), factory: () => new QueryDirective(),
contentQueries: () => { contentQueries: (dirIndex) => {
// @ContentChildren('foo, bar, baz', {descendants: true}) fooBars: // @ContentChildren('foo, bar, baz', {descendants: true}) fooBars:
// QueryList<ElementRef>; // QueryList<ElementRef>;
registerContentQuery(query(null, ['foo'], false)); registerContentQuery(query(null, ['foo'], false), dirIndex);
}, },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
@ -2227,9 +2274,9 @@ describe('query', () => {
selectors: [['', 'shallow-query', '']], selectors: [['', 'shallow-query', '']],
exportAs: 'shallow-query', exportAs: 'shallow-query',
factory: () => new ShallowQueryDirective(), factory: () => new ShallowQueryDirective(),
contentQueries: () => { contentQueries: (dirIndex) => {
// @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>; // @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>;
registerContentQuery(query(null, ['foo'], false)); registerContentQuery(query(null, ['foo'], false), dirIndex);
}, },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
@ -2247,9 +2294,9 @@ describe('query', () => {
selectors: [['', 'deep-query', '']], selectors: [['', 'deep-query', '']],
exportAs: 'deep-query', exportAs: 'deep-query',
factory: () => new DeepQueryDirective(), factory: () => new DeepQueryDirective(),
contentQueries: () => { contentQueries: (dirIndex) => {
// @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>; // @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>;
registerContentQuery(query(null, ['foo'], true)); registerContentQuery(query(null, ['foo'], true), dirIndex);
}, },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;

View File

@ -23,12 +23,13 @@ import {CreateComponentOptions} from '../../src/render3/component';
import {discoverDirectives, getContext, isComponentInstance} from '../../src/render3/context_discovery'; import {discoverDirectives, getContext, isComponentInstance} from '../../src/render3/context_discovery';
import {extractDirectiveDef, extractPipeDef} from '../../src/render3/definition'; import {extractDirectiveDef, extractPipeDef} from '../../src/render3/definition';
import {NG_ELEMENT_ID} from '../../src/render3/fields'; import {NG_ELEMENT_ID} from '../../src/render3/fields';
import {ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, PublicFeature, RenderFlags, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index'; import {ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, RenderFlags, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
import {_getViewData, renderTemplate} from '../../src/render3/instructions'; import {renderTemplate} from '../../src/render3/instructions';
import {DirectiveDefList, DirectiveTypesOrFactory, PipeDef, PipeDefList, PipeTypesOrFactory} from '../../src/render3/interfaces/definition'; import {DirectiveDefList, DirectiveTypesOrFactory, PipeDef, PipeDefList, PipeTypesOrFactory} from '../../src/render3/interfaces/definition';
import {PlayerHandler} from '../../src/render3/interfaces/player'; import {PlayerHandler} from '../../src/render3/interfaces/player';
import {RElement, RText, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer'; import {RElement, RText, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
import {HEADER_OFFSET, LViewData} from '../../src/render3/interfaces/view'; import {HEADER_OFFSET, LViewData} from '../../src/render3/interfaces/view';
import {getViewData} from '../../src/render3/state';
import {Sanitizer} from '../../src/sanitization/security'; import {Sanitizer} from '../../src/sanitization/security';
import {Type} from '../../src/type'; import {Type} from '../../src/type';
@ -275,7 +276,6 @@ export function createComponent(
factory: () => new Component, factory: () => new Component,
template: template, template: template,
viewQuery: viewQuery, viewQuery: viewQuery,
features: [PublicFeature],
directives: directives, directives: directives,
pipes: pipes pipes: pipes
}); });
@ -289,7 +289,6 @@ export function createDirective(
type: Directive, type: Directive,
selectors: [['', name, '']], selectors: [['', name, '']],
factory: () => new Directive(), factory: () => new Directive(),
features: [PublicFeature],
exportAs: exportAs, exportAs: exportAs,
}); });
}; };
@ -297,7 +296,7 @@ export function createDirective(
/** Gets the directive on the given node at the given index */ /** Gets the directive on the given node at the given index */
export function getDirectiveOnNode(nodeIndex: number, dirIndex: number = 0) { export function getDirectiveOnNode(nodeIndex: number, dirIndex: number = 0) {
const directives = discoverDirectives(nodeIndex + HEADER_OFFSET, _getViewData(), true); const directives = discoverDirectives(nodeIndex + HEADER_OFFSET, getViewData(), true);
if (directives == null) { if (directives == null) {
throw new Error(`No directives exist on node in slot ${nodeIndex}`); throw new Error(`No directives exist on node in slot ${nodeIndex}`);
} }

View File

@ -8,10 +8,9 @@
import {Component, ComponentFactoryResolver, ElementRef, EmbeddedViewRef, NgModuleRef, Pipe, PipeTransform, RendererFactory2, TemplateRef, ViewContainerRef, createInjector, defineInjector, ɵAPP_ROOT as APP_ROOT, ɵNgModuleDef as NgModuleDef} from '../../src/core'; import {Component, ComponentFactoryResolver, ElementRef, EmbeddedViewRef, NgModuleRef, Pipe, PipeTransform, RendererFactory2, TemplateRef, ViewContainerRef, createInjector, defineInjector, ɵAPP_ROOT as APP_ROOT, ɵNgModuleDef as NgModuleDef} from '../../src/core';
import {ViewEncapsulation} from '../../src/metadata'; import {ViewEncapsulation} from '../../src/metadata';
import {directiveInject} from '../../src/render3/di';
import {AttributeMarker, NgOnChangesFeature, defineComponent, defineDirective, definePipe, injectComponentFactoryResolver, load} from '../../src/render3/index'; import {AttributeMarker, NgOnChangesFeature, defineComponent, defineDirective, definePipe, injectComponentFactoryResolver, load} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation3, nextContext, projection, projectionDef, reference, template, text, textBinding} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, directiveInject, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation3, nextContext, projection, projectionDef, reference, template, text, textBinding} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition'; import {RenderFlags} from '../../src/render3/interfaces/definition';
import {templateRefExtractor} from '../../src/render3/view_engine_compatibility_prebound'; import {templateRefExtractor} from '../../src/render3/view_engine_compatibility_prebound';
import {NgModuleFactory} from '../../src/render3/ng_module_ref'; import {NgModuleFactory} from '../../src/render3/ng_module_ref';

View File

@ -717,7 +717,7 @@ export interface ResolvedReflectiveProvider {
resolvedFactories: ResolvedReflectiveFactory[]; resolvedFactories: ResolvedReflectiveFactory[];
} }
export declare function resolveForwardRef(type: any): any; export declare function resolveForwardRef<T>(type: T): T;
/** @deprecated */ /** @deprecated */
export declare abstract class RootRenderer { export declare abstract class RootRenderer {