fix(ivy): objects like ElementRef should not use a special injection fn (#26064)

PR Close #26064
This commit is contained in:
Kara Erickson 2018-09-21 18:38:13 -07:00
parent 482e12c940
commit 6a62ed2245
56 changed files with 1367 additions and 1073 deletions

View File

@ -68,21 +68,9 @@ export function getConstructorDependencies(
const importedSymbol = reflector.getImportOfIdentifier(tokenExpr); const importedSymbol = reflector.getImportOfIdentifier(tokenExpr);
if (importedSymbol !== null && importedSymbol.from === '@angular/core') { if (importedSymbol !== null && importedSymbol.from === '@angular/core') {
switch (importedSymbol.name) { switch (importedSymbol.name) {
case 'ChangeDetectorRef':
resolved = R3ResolvedDependencyType.ChangeDetectorRef;
break;
case 'ElementRef':
resolved = R3ResolvedDependencyType.ElementRef;
break;
case 'Injector': case 'Injector':
resolved = R3ResolvedDependencyType.Injector; resolved = R3ResolvedDependencyType.Injector;
break; break;
case 'TemplateRef':
resolved = R3ResolvedDependencyType.TemplateRef;
break;
case 'ViewContainerRef':
resolved = R3ResolvedDependencyType.ViewContainerRef;
break;
case 'Renderer2': case 'Renderer2':
resolved = R3ResolvedDependencyType.Renderer2; resolved = R3ResolvedDependencyType.Renderer2;
break; break;

View File

@ -648,6 +648,49 @@ describe('compiler compliance', () => {
expectEmit(source, HostBindingCompDeclaration, 'Invalid host binding code'); expectEmit(source, HostBindingCompDeclaration, 'Invalid host binding code');
}); });
it('should not treat ElementRef, ViewContainerRef, or ChangeDetectorRef specially when injecting',
() => {
const files = {
app: {
'spec.ts': `
import {Component, NgModule, ElementRef, ChangeDetectorRef, ViewContainerRef} from '@angular/core';
@Component({
selector: 'my-component',
template: ''
})
export class MyComponent {
constructor(public el: ElementRef, public vcr: ViewContainerRef, public cdr: ChangeDetectorRef) {}
}
@NgModule({declarations: [MyComponent]})
export class MyModule {}
`
}
};
const MyComponentDefinition = `
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
selectors: [["my-component"]],
factory: function MyComponent_Factory(t) {
return new (t || MyComponent)(
$r3$.ɵdirectiveInject(ElementRef), $r3$.ɵdirectiveInject(ViewContainerRef),
$r3$.ɵdirectiveInject(ChangeDetectorRef));
},
features: [$r3$.ɵPublicFeature],
consts: 0,
vars: 0,
template: function MyComponent_Template(rf, ctx) {}
});`;
const result = compile(files, angularFiles);
const source = result.source;
expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef');
});
it('should support structural directives', () => { it('should support structural directives', () => {
const files = { const files = {
app: { app: {
@ -677,7 +720,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$.ɵinjectTemplateRef()); }, factory: function IfDirective_Factory(t) { return new (t || IfDirective)($r3$.ɵdirectiveInject(TemplateRef)); },
features: [$r3$.ɵPublicFeature] features: [$r3$.ɵPublicFeature]
});`; });`;
const MyComponentDefinition = ` const MyComponentDefinition = `
@ -1703,7 +1746,7 @@ describe('compiler compliance', () => {
type: ForOfDirective, type: ForOfDirective,
selectors: [["", "forOf", ""]], selectors: [["", "forOf", ""]],
factory: function ForOfDirective_Factory(t) { factory: function ForOfDirective_Factory(t) {
return new (t || ForOfDirective)($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef()); return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
}, },
features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature], features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature],
inputs: {forOf: "forOf"} inputs: {forOf: "forOf"}
@ -1779,7 +1822,7 @@ describe('compiler compliance', () => {
type: ForOfDirective, type: ForOfDirective,
selectors: [["", "forOf", ""]], selectors: [["", "forOf", ""]],
factory: function ForOfDirective_Factory(t) { factory: function ForOfDirective_Factory(t) {
return new (t || ForOfDirective)($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef()); return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
}, },
features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature], features: [$r3$.ɵPublicFeature, $r3$.ɵNgOnChangesFeature],
inputs: {forOf: "forOf"} inputs: {forOf: "forOf"}

View File

@ -480,7 +480,7 @@ describe('ngtsc behavioral tests', () => {
const jsContents = getContents('test.js'); const jsContents = getContents('test.js');
expect(jsContents) expect(jsContents)
.toContain( .toContain(
`factory: function FooCmp_Factory(t) { return new (t || FooCmp)(i0.ɵinjectAttribute("test"), i0.ɵinjectChangeDetectorRef(), i0.ɵinjectElementRef(), i0.ɵdirectiveInject(i0.INJECTOR), i0.ɵinjectRenderer2(), i0.ɵinjectTemplateRef(), i0.ɵinjectViewContainerRef()); }`); `factory: function FooCmp_Factory(t) { return new (t || FooCmp)(i0.ɵinjectAttribute("test"), i0.ɵdirectiveInject(ChangeDetectorRef), i0.ɵdirectiveInject(ElementRef), i0.ɵdirectiveInject(i0.INJECTOR), i0.ɵinjectRenderer2(), i0.ɵdirectiveInject(TemplateRef), i0.ɵdirectiveInject(ViewContainerRef)); }`);
}); });
it('should generate queries for components', () => { it('should generate queries for components', () => {

View File

@ -101,30 +101,10 @@ export enum R3ResolvedDependencyType {
*/ */
Injector = 2, Injector = 2,
/**
* The dependency is for `ElementRef`.
*/
ElementRef = 3,
/**
* The dependency is for `TemplateRef`.
*/
TemplateRef = 4,
/**
* The dependency is for `ViewContainerRef`.
*/
ViewContainerRef = 5,
/**
* The dependency is for `ChangeDetectorRef`.
*/
ChangeDetectorRef = 6,
/** /**
* The dependency is for `Renderer2`. * The dependency is for `Renderer2`.
*/ */
Renderer2 = 7, Renderer2 = 3,
} }
/** /**
@ -282,14 +262,6 @@ function compileInjectDependency(
case R3ResolvedDependencyType.Attribute: case R3ResolvedDependencyType.Attribute:
// In the case of attributes, the attribute name in question is given as the token. // In the case of attributes, the attribute name in question is given as the token.
return o.importExpr(R3.injectAttribute).callFn([dep.token]); return o.importExpr(R3.injectAttribute).callFn([dep.token]);
case R3ResolvedDependencyType.ElementRef:
return o.importExpr(R3.injectElementRef).callFn([]);
case R3ResolvedDependencyType.TemplateRef:
return o.importExpr(R3.injectTemplateRef).callFn([]);
case R3ResolvedDependencyType.ViewContainerRef:
return o.importExpr(R3.injectViewContainerRef).callFn([]);
case R3ResolvedDependencyType.ChangeDetectorRef:
return o.importExpr(R3.injectChangeDetectorRef).callFn([]);
case R3ResolvedDependencyType.Renderer2: case R3ResolvedDependencyType.Renderer2:
return o.importExpr(R3.injectRenderer2).callFn([]); return o.importExpr(R3.injectRenderer2).callFn([]);
default: default:
@ -320,13 +292,7 @@ export function dependenciesFromGlobalMetadata(
if (dependency.token) { if (dependency.token) {
const tokenRef = tokenReference(dependency.token); const tokenRef = tokenReference(dependency.token);
let resolved: R3ResolvedDependencyType = R3ResolvedDependencyType.Token; let resolved: R3ResolvedDependencyType = R3ResolvedDependencyType.Token;
if (tokenRef === elementRef) { if (tokenRef === injectorRef) {
resolved = R3ResolvedDependencyType.ElementRef;
} else if (tokenRef === templateRef) {
resolved = R3ResolvedDependencyType.TemplateRef;
} else if (tokenRef === viewContainerRef) {
resolved = R3ResolvedDependencyType.ViewContainerRef;
} else if (tokenRef === injectorRef) {
resolved = R3ResolvedDependencyType.Injector; resolved = R3ResolvedDependencyType.Injector;
} else if (tokenRef === renderer2) { } else if (tokenRef === renderer2) {
resolved = R3ResolvedDependencyType.Renderer2; resolved = R3ResolvedDependencyType.Renderer2;
@ -363,4 +329,4 @@ function isDelegatedMetadata(meta: R3FactoryMetadata): meta is R3DelegatedFactor
function isExpressionFactoryMetadata(meta: R3FactoryMetadata): meta is R3ExpressionFactoryMetadata { function isExpressionFactoryMetadata(meta: R3FactoryMetadata): meta is R3ExpressionFactoryMetadata {
return (meta as any).expression !== undefined; return (meta as any).expression !== undefined;
} }

View File

@ -106,16 +106,6 @@ export class Identifiers {
static injectAttribute: o.ExternalReference = {name: 'ɵinjectAttribute', moduleName: CORE}; static injectAttribute: o.ExternalReference = {name: 'ɵinjectAttribute', moduleName: CORE};
static injectElementRef: o.ExternalReference = {name: 'ɵinjectElementRef', moduleName: CORE};
static injectTemplateRef: o.ExternalReference = {name: 'ɵinjectTemplateRef', moduleName: CORE};
static injectViewContainerRef:
o.ExternalReference = {name: 'ɵinjectViewContainerRef', moduleName: CORE};
static injectChangeDetectorRef:
o.ExternalReference = {name: 'ɵinjectChangeDetectorRef', moduleName: CORE};
static injectRenderer2: o.ExternalReference = {name: 'ɵinjectRenderer2', moduleName: CORE}; static injectRenderer2: o.ExternalReference = {name: 'ɵinjectRenderer2', moduleName: CORE};
static directiveInject: o.ExternalReference = {name: 'ɵdirectiveInject', moduleName: CORE}; static directiveInject: o.ExternalReference = {name: 'ɵdirectiveInject', moduleName: CORE};

View File

@ -43,7 +43,7 @@ function baseDirectiveFields(
definitionMap.set('selectors', createDirectiveSelector(meta.selector !)); definitionMap.set('selectors', createDirectiveSelector(meta.selector !));
// e.g. `factory: () => new MyApp(injectElementRef())` // e.g. `factory: () => new MyApp(directiveInject(ElementRef))`
const result = compileFactoryFunction({ const result = compileFactoryFunction({
name: meta.name, name: meta.name,
type: meta.type, type: meta.type,

View File

@ -9,9 +9,13 @@ ng_module(
"*.ts", "*.ts",
"src/**/*.ts", "src/**/*.ts",
], ],
exclude = ["src/ivy_switch.ts"], exclude = [
"src/ivy_switch/compiler/index.ts",
"src/ivy_switch/runtime/index.ts",
],
) + [ ) + [
":ivy_switch", ":ivy_switch_compiler",
":ivy_switch_runtime",
], ],
module_name = "@angular/core", module_name = "@angular/core",
deps = [ deps = [
@ -42,19 +46,27 @@ ng_package(
## Controls if Ivy is enabled. (Temporary target until we permanently switch over to Ivy) ## Controls if Ivy is enabled. (Temporary target until we permanently switch over to Ivy)
## ##
## This file generates `src/ivy_switch.ts` file which reexports symbols for `ViewEngine` or `Ivy.` ## This file generates the `src/ivy_switch/compiler/index.ts` and `src/ivy_switch/runtime/index.ts` files which
## - append `--define=compile=legacy` (default) to `bazel` command to reexport `./ivy_switch_legacy` ## reexport symbols for `ViewEngine` or `Ivy.`
## and use `ViewEngine` ## - append `--define=compile=legacy` (default) to `bazel` command to reexport `./legacy` from each folder
## - append `--define=compile=jit` to `bazel` command to rexport `./ivy_switch_jit` and use `Ivy` ## in the 'ivy_switch' directory and use `ViewEngine`
## - append `--define=compile=local` to `bazel` command to rexport `./ivy_switch_jit` and use `Ivy` ## - append `--define=compile=jit` to `bazel` command to rexport `./jit` from each folder in the `ivy_switch`
## directory and use `Ivy`
## - append `--define=compile=local` to `bazel` command to rexport `./ivy_switch/compiler/jit` and use `Ivy`
## in the local analysis mode. (run as part of `ngtsc`) ## in the local analysis mode. (run as part of `ngtsc`)
## ##
## NOTE: `--define=compile=jit` works with any `bazel` command or target across the repo. ## NOTE: `--define=compile=jit` works with any `bazel` command or target across the repo.
## ##
## See: `//tools/bazel.rc` where `--define=ivy=false` is defined as default. ## See: `//tools/bazel.rc` where `--define=ivy=false` is defined as default.
## See: `./src/ivy_switch.ts` for more details. ## See: `./src/ivy_switch/compiler/index.ts` for more details.
genrule( genrule(
name = "ivy_switch", name = "ivy_switch_compiler",
outs = ["src/ivy_switch.ts"], outs = ["src/ivy_switch/compiler/index.ts"],
cmd = "echo export '*' from \"'./ivy_switch_$(compile)';\" > $@", cmd = "echo export '*' from \"'./$(compile)';\" > $@",
)
genrule(
name = "ivy_switch_runtime",
outs = ["src/ivy_switch/runtime/index.ts"],
cmd = "echo export '*' from \"'./$(compile)';\" > $@",
) )

View File

@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {R3_CHANGE_DETECTOR_REF_FACTORY} from '../ivy_switch/runtime/index';
/** /**
* Base class for Angular Views, provides change detection functionality. * Base class for Angular Views, provides change detection functionality.
* A change-detection tree collects all views that are to be checked for changes. * A change-detection tree collects all views that are to be checked for changes.
@ -103,4 +105,7 @@ export abstract class ChangeDetectorRef {
* *
*/ */
abstract reattach(): void; abstract reattach(): void;
/** @internal */
static __NG_ELEMENT_ID__: () => ChangeDetectorRef = () => R3_CHANGE_DETECTOR_REF_FACTORY();
} }

View File

@ -16,7 +16,7 @@ export {Console as ɵConsole} from './console';
export {InjectableDef as ɵInjectableDef, InjectorDef as ɵInjectorDef, getInjectableDef as ɵgetInjectableDef} from './di/defs'; export {InjectableDef as ɵInjectableDef, InjectorDef as ɵInjectorDef, getInjectableDef as ɵgetInjectableDef} from './di/defs';
export {inject as ɵinject, setCurrentInjector as ɵsetCurrentInjector} from './di/injector'; export {inject as ɵinject, setCurrentInjector as ɵsetCurrentInjector} from './di/injector';
export {APP_ROOT as ɵAPP_ROOT} from './di/scope'; export {APP_ROOT as ɵAPP_ROOT} from './di/scope';
export {ivyEnabled as ɵivyEnabled} from './ivy_switch'; export {ivyEnabled as ɵivyEnabled} from './ivy_switch/compiler/index';
export {ComponentFactory as ɵComponentFactory} from './linker/component_factory'; export {ComponentFactory as ɵComponentFactory} from './linker/component_factory';
export {CodegenComponentFactoryResolver as ɵCodegenComponentFactoryResolver} from './linker/component_factory_resolver'; export {CodegenComponentFactoryResolver as ɵCodegenComponentFactoryResolver} from './linker/component_factory_resolver';
export {resolveComponentResources as ɵresolveComponentResources} from './metadata/resource_loading'; export {resolveComponentResources as ɵresolveComponentResources} from './metadata/resource_loading';

View File

@ -21,10 +21,6 @@ export {
DirectiveType as ɵDirectiveType, DirectiveType as ɵDirectiveType,
RenderFlags as ɵRenderFlags, RenderFlags as ɵRenderFlags,
directiveInject as ɵdirectiveInject, directiveInject as ɵdirectiveInject,
injectElementRef as ɵinjectElementRef,
injectTemplateRef as ɵinjectTemplateRef,
injectViewContainerRef as ɵinjectViewContainerRef,
injectChangeDetectorRef as ɵinjectChangeDetectorRef,
injectRenderer2 as ɵinjectRenderer2, injectRenderer2 as ɵinjectRenderer2,
injectAttribute as ɵinjectAttribute, injectAttribute as ɵinjectAttribute,
getFactoryOf as ɵgetFactoryOf, getFactoryOf as ɵgetFactoryOf,
@ -187,6 +183,15 @@ export {
R3_COMPILE_INJECTABLE__POST_NGCC__ as ɵR3_COMPILE_INJECTABLE__POST_NGCC__, R3_COMPILE_INJECTABLE__POST_NGCC__ as ɵR3_COMPILE_INJECTABLE__POST_NGCC__,
R3_COMPILE_NGMODULE__POST_NGCC__ as ɵR3_COMPILE_NGMODULE__POST_NGCC__, R3_COMPILE_NGMODULE__POST_NGCC__ as ɵR3_COMPILE_NGMODULE__POST_NGCC__,
R3_COMPILE_PIPE__POST_NGCC__ as ɵR3_COMPILE_PIPE__POST_NGCC__, R3_COMPILE_PIPE__POST_NGCC__ as ɵR3_COMPILE_PIPE__POST_NGCC__,
ivyEnable__POST_NGCC__ as ɵivyEnable__POST_NGCC__ ivyEnable__POST_NGCC__ as ɵivyEnable__POST_NGCC__,
} from './ivy_switch_legacy'; } from './ivy_switch/compiler/legacy';
export {
R3_ELEMENT_REF_FACTORY__POST_NGCC__ as ɵR3_ELEMENT_REF_FACTORY__POST_NGCC__,
R3_TEMPLATE_REF_FACTORY__POST_NGCC__ as ɵR3_TEMPLATE_REF_FACTORY__POST_NGCC__,
R3_CHANGE_DETECTOR_REF_FACTORY__POST_NGCC__ as ɵR3_CHANGE_DETECTOR_REF_FACTORY__POST_NGCC__,
R3_VIEW_CONTAINER_REF_FACTORY__POST_NGCC__ as ɵR3_VIEW_CONTAINER_REF_FACTORY__POST_NGCC__,
} from './ivy_switch/runtime/legacy';
// clang-format on // clang-format on

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 {R3_COMPILE_INJECTABLE} from '../ivy_switch'; import {R3_COMPILE_INJECTABLE} from '../ivy_switch/compiler/index';
import {Type} from '../type'; import {Type} from '../type';
import {makeDecorator} from '../util/decorators'; import {makeDecorator} from '../util/decorators';

View File

@ -12,6 +12,6 @@
* For more information on how to run and debug tests with either Ivy or View Engine (legacy), * For more information on how to run and debug tests with either Ivy or View Engine (legacy),
* please see [BAZEL.md](./docs/BAZEL.md). * please see [BAZEL.md](./docs/BAZEL.md).
*/ */
export * from './ivy_switch_legacy'; export * from './legacy';
// TODO(alxhub): debug why metadata doesn't properly propagate through this file. // TODO(alxhub): debug why metadata doesn't properly propagate through this file.

View File

@ -6,10 +6,10 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {compileComponent, compileDirective} from './render3/jit/directive'; import {compileComponent, compileDirective} from '../../render3/jit/directive';
import {compileInjectable} from './render3/jit/injectable'; import {compileInjectable} from '../../render3/jit/injectable';
import {compileNgModule} from './render3/jit/module'; import {compileNgModule} from '../../render3/jit/module';
import {compilePipe} from './render3/jit/pipe'; import {compilePipe} from '../../render3/jit/pipe';
export const ivyEnabled = true; export const ivyEnabled = true;
export const R3_COMPILE_COMPONENT = compileComponent; export const R3_COMPILE_COMPONENT = compileComponent;

View File

@ -6,15 +6,16 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {InjectableType, InjectorType, defineInjectable, defineInjector, getInjectableDef} from './di/defs'; import {InjectableType, InjectorType, defineInjectable, defineInjector, getInjectableDef} from '../../di/defs';
import {InjectableProvider} from './di/injectable'; import {InjectableProvider} from '../../di/injectable';
import {inject, injectArgs} from './di/injector'; import {inject, injectArgs} from '../../di/injector';
import {ClassSansProvider, ConstructorSansProvider, ExistingSansProvider, FactorySansProvider, StaticClassSansProvider, ValueProvider, ValueSansProvider} from './di/provider'; import {ClassSansProvider, ConstructorSansProvider, ExistingSansProvider, FactorySansProvider, StaticClassSansProvider, ValueProvider, ValueSansProvider} from '../../di/provider';
import {NgModule} from '../../metadata';
import {ReflectionCapabilities} from '../../reflection/reflection_capabilities';
import {Type} from '../../type';
import {getClosureSafeProperty} from '../../util/property';
import * as ivyOn from './ivy_switch_on'; import * as ivyOn from './ivy_switch_on';
import {NgModule} from './metadata';
import {ReflectionCapabilities} from './reflection/reflection_capabilities';
import {Type} from './type';
import {getClosureSafeProperty} from './util/property';
function noop() {} function noop() {}
@ -25,6 +26,7 @@ export const R3_COMPILE_DIRECTIVE__POST_NGCC__: DirectiveCompiler = ivyOn.R3_COM
export const R3_COMPILE_INJECTABLE__POST_NGCC__: DirectiveCompiler = ivyOn.R3_COMPILE_INJECTABLE; export const R3_COMPILE_INJECTABLE__POST_NGCC__: DirectiveCompiler = ivyOn.R3_COMPILE_INJECTABLE;
export const R3_COMPILE_NGMODULE__POST_NGCC__: DirectiveCompiler = ivyOn.R3_COMPILE_NGMODULE; export const R3_COMPILE_NGMODULE__POST_NGCC__: DirectiveCompiler = ivyOn.R3_COMPILE_NGMODULE;
export const R3_COMPILE_PIPE__POST_NGCC__: DirectiveCompiler = ivyOn.R3_COMPILE_PIPE; export const R3_COMPILE_PIPE__POST_NGCC__: DirectiveCompiler = ivyOn.R3_COMPILE_PIPE;
export const ivyEnable__POST_NGCC__: boolean = ivyOn.ivyEnabled; export const ivyEnable__POST_NGCC__: boolean = ivyOn.ivyEnabled;
const R3_COMPILE_COMPONENT__PRE_NGCC__: DirectiveCompiler = noop; const R3_COMPILE_COMPONENT__PRE_NGCC__: DirectiveCompiler = noop;
@ -32,6 +34,7 @@ const R3_COMPILE_DIRECTIVE__PRE_NGCC__: DirectiveCompiler = noop;
const R3_COMPILE_INJECTABLE__PRE_NGCC__: DirectiveCompiler = preR3InjectableCompile; const R3_COMPILE_INJECTABLE__PRE_NGCC__: DirectiveCompiler = preR3InjectableCompile;
const R3_COMPILE_NGMODULE__PRE_NGCC__: DirectiveCompiler = preR3NgModuleCompile; const R3_COMPILE_NGMODULE__PRE_NGCC__: DirectiveCompiler = preR3NgModuleCompile;
const R3_COMPILE_PIPE__PRE_NGCC__: DirectiveCompiler = noop; const R3_COMPILE_PIPE__PRE_NGCC__: DirectiveCompiler = noop;
const ivyEnable__PRE_NGCC__ = false; const ivyEnable__PRE_NGCC__ = false;
export const ivyEnabled = ivyEnable__PRE_NGCC__; export const ivyEnabled = ivyEnable__PRE_NGCC__;
@ -111,4 +114,4 @@ function preR3InjectableCompile(
factory: convertInjectableProviderToFactory(injectableType, options), factory: convertInjectableProviderToFactory(injectableType, options),
}); });
} }
} }

View File

@ -0,0 +1,15 @@
/**
* @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
*/
/**
* This file is used to control if the default rendering pipeline should be `ViewEngine` or `Ivy`.
*
* For more information on how to run and debug tests with either Ivy or View Engine (legacy),
* please see [BAZEL.md](./docs/BAZEL.md).
*/
export * from './legacy';

View File

@ -0,0 +1,14 @@
/**
* @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 {injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../render3/view_engine_compatibility';
export const R3_ELEMENT_REF_FACTORY = injectElementRef;
export const R3_TEMPLATE_REF_FACTORY = injectTemplateRef;
export const R3_CHANGE_DETECTOR_REF_FACTORY = injectChangeDetectorRef;
export const R3_VIEW_CONTAINER_REF_FACTORY = injectViewContainerRef;

View File

@ -0,0 +1,10 @@
/**
* @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
*/
export * from './ivy_switch_on';

View File

@ -0,0 +1,31 @@
/**
* @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 * as ivyOn from './ivy_switch_on';
function noopFactory(...tokens: any[]): any {}
type FactoryFunction<T = any> = (...tokens: any[]) => T;
export const R3_ELEMENT_REF_FACTORY__POST_NGCC__: FactoryFunction = ivyOn.R3_ELEMENT_REF_FACTORY;
export const R3_TEMPLATE_REF_FACTORY__POST_NGCC__: FactoryFunction = ivyOn.R3_TEMPLATE_REF_FACTORY;
export const R3_CHANGE_DETECTOR_REF_FACTORY__POST_NGCC__: FactoryFunction =
ivyOn.R3_CHANGE_DETECTOR_REF_FACTORY;
export const R3_VIEW_CONTAINER_REF_FACTORY__POST_NGCC__: FactoryFunction =
ivyOn.R3_VIEW_CONTAINER_REF_FACTORY;
export const R3_ELEMENT_REF_FACTORY__PRE_NGCC__ = noopFactory;
export const R3_TEMPLATE_REF_FACTORY__PRE_NGCC__ = noopFactory;
export const R3_CHANGE_DETECTOR_REF_FACTORY__PRE_NGCC__ = noopFactory;
export const R3_VIEW_CONTAINER_REF_FACTORY__PRE_NGCC__ = noopFactory;
export let R3_ELEMENT_REF_FACTORY = R3_ELEMENT_REF_FACTORY__PRE_NGCC__;
export let R3_TEMPLATE_REF_FACTORY = R3_TEMPLATE_REF_FACTORY__PRE_NGCC__;
export let R3_CHANGE_DETECTOR_REF_FACTORY = R3_CHANGE_DETECTOR_REF_FACTORY__PRE_NGCC__;
export let R3_VIEW_CONTAINER_REF_FACTORY = R3_VIEW_CONTAINER_REF_FACTORY__PRE_NGCC__;

View File

@ -0,0 +1,10 @@
/**
* @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
*/
export * from './ivy_switch_on';

View File

@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {R3_ELEMENT_REF_FACTORY} from '../ivy_switch/runtime/index';
/** /**
* A wrapper around a native element inside of a View. * A wrapper around a native element inside of a View.
* *
@ -46,4 +48,7 @@ export class ElementRef<T = any> {
public nativeElement: T; public nativeElement: T;
constructor(nativeElement: T) { this.nativeElement = nativeElement; } constructor(nativeElement: T) { this.nativeElement = nativeElement; }
/** @internal */
static __NG_ELEMENT_ID__: () => ElementRef = () => R3_ELEMENT_REF_FACTORY(ElementRef);
} }

View File

@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {R3_TEMPLATE_REF_FACTORY} from '../ivy_switch/runtime/index';
import {ElementRef} from './element_ref'; import {ElementRef} from './element_ref';
import {EmbeddedViewRef} from './view_ref'; import {EmbeddedViewRef} from './view_ref';
@ -14,12 +16,12 @@ import {EmbeddedViewRef} from './view_ref';
* Represents an embedded template that can be used to instantiate embedded views. * Represents an embedded template that can be used to instantiate embedded views.
* To instantiate embedded views based on a template, use the `ViewContainerRef` * To instantiate embedded views based on a template, use the `ViewContainerRef`
* method `createEmbeddedView()`. * method `createEmbeddedView()`.
* *
* Access a `TemplateRef` instance by placing a directive on an `<ng-template>` * Access a `TemplateRef` instance by placing a directive on an `<ng-template>`
* element (or directive prefixed with `*`). The `TemplateRef` for the embedded view * element (or directive prefixed with `*`). The `TemplateRef` for the embedded view
* is injected into the constructor of the directive, * is injected into the constructor of the directive,
* using the `TemplateRef` token. * using the `TemplateRef` token.
* *
* You can also use a `Query` to find a `TemplateRef` associated with * You can also use a `Query` to find a `TemplateRef` associated with
* a component or a directive. * a component or a directive.
* *
@ -48,4 +50,8 @@ export abstract class TemplateRef<C> {
* @returns The new view object. * @returns The new view object.
*/ */
abstract createEmbeddedView(context: C): EmbeddedViewRef<C>; abstract createEmbeddedView(context: C): EmbeddedViewRef<C>;
/** @internal */
static __NG_ELEMENT_ID__:
() => TemplateRef<any> = () => R3_TEMPLATE_REF_FACTORY(TemplateRef, ElementRef)
} }

View File

@ -7,6 +7,8 @@
*/ */
import {Injector} from '../di/injector'; import {Injector} from '../di/injector';
import {R3_VIEW_CONTAINER_REF_FACTORY} from '../ivy_switch/runtime/index';
import {ComponentFactory, ComponentRef} from './component_factory'; import {ComponentFactory, ComponentRef} from './component_factory';
import {ElementRef} from './element_ref'; import {ElementRef} from './element_ref';
import {NgModuleRef} from './ng_module_factory'; import {NgModuleRef} from './ng_module_factory';
@ -139,4 +141,8 @@ export abstract class ViewContainerRef {
* If not specified, the last view in the container is detached. * If not specified, the last view in the container is detached.
*/ */
abstract detach(index?: number): ViewRef|null; abstract detach(index?: number): ViewRef|null;
/** @internal */
static __NG_ELEMENT_ID__:
() => ViewContainerRef = () => R3_VIEW_CONTAINER_REF_FACTORY(ViewContainerRef, ElementRef)
} }

View File

@ -8,7 +8,7 @@
import {ChangeDetectionStrategy} from '../change_detection/constants'; import {ChangeDetectionStrategy} from '../change_detection/constants';
import {Provider} from '../di'; import {Provider} from '../di';
import {R3_COMPILE_COMPONENT, R3_COMPILE_DIRECTIVE, R3_COMPILE_PIPE} from '../ivy_switch'; import {R3_COMPILE_COMPONENT, R3_COMPILE_DIRECTIVE, R3_COMPILE_PIPE} from '../ivy_switch/compiler/index';
import {NG_BASE_DEF} from '../render3/fields'; import {NG_BASE_DEF} from '../render3/fields';
import {Type} from '../type'; import {Type} from '../type';
import {TypeDecorator, makeDecorator, makePropDecorator} from '../util/decorators'; import {TypeDecorator, makeDecorator, makePropDecorator} from '../util/decorators';

View File

@ -8,7 +8,7 @@
import {ApplicationRef} from '../application_ref'; import {ApplicationRef} from '../application_ref';
import {Provider} from '../di/provider'; import {Provider} from '../di/provider';
import {R3_COMPILE_NGMODULE} from '../ivy_switch'; import {R3_COMPILE_NGMODULE} from '../ivy_switch/compiler/index';
import {Type} from '../type'; import {Type} from '../type';
import {TypeDecorator, makeDecorator} from '../util/decorators'; import {TypeDecorator, makeDecorator} from '../util/decorators';

View File

@ -382,17 +382,19 @@ NOTE:
An interesting thing about these objects is that they are not memoized `injector.get(ElementRef) !== injector.get(ElementRef)`. An interesting thing about these objects is that they are not memoized `injector.get(ElementRef) !== injector.get(ElementRef)`.
This could be considered a bug, it means that we don't have to allocate storage space for them. This could be considered a bug, it means that we don't have to allocate storage space for them.
We should treat these special objects like any other token. `directiveInject()` already reads a special `NG_ELEMENT_ID`
property set on directives to locate their bit in the bloom filter. We can set this same property on special objects,
but point to a factory function rather than an element ID number. When we check that property in `directiveInject()`
and see that it's a function, we know to invoke the factory function directly instead of searching the node tree.
```typescript ```typescript
@Injectable({
provideIn: '__node__' as any // Special token not available to the developer
useFactory: injectElementRef // existing function which generates ElementRef
})
class ElementRef { class ElementRef {
... ...
static __NG_ELEMENT_ID__ = () => injectElementRef();
} }
``` ```
Consequence of the above is that `injector.get(ElementRef)` returns an instance of `ElementRef` without `Injector` having to know about `ElementRef` at compile time. Consequence of the above is that `directiveInject(ElementRef)` returns an instance of `ElementRef` without `Injector` having to know about `ElementRef` at compile time.
# `EXPANDO` and Injecting the `Injector`. # `EXPANDO` and Injecting the `Injector`.
@ -421,10 +423,7 @@ function inject(token: any): any {
let injectableDef; let injectableDef;
if (typeof token === 'function' && injectableDef = token.ngInjectableDef) { if (typeof token === 'function' && injectableDef = token.ngInjectableDef) {
const provideIn = injectableDef.provideIn; const provideIn = injectableDef.provideIn;
if (provideIn === '__node__') { if (provideIn === '__node_injector__') {
// if it is a special object just call its factory
return injectableDef.useFactory();
} else if (provideIn === '__node_injector__') {
// if we are injecting `Injector` than create a wrapper object around the inject but which // if we are injecting `Injector` than create a wrapper object around the inject but which
// is bound to the current node. // is bound to the current node.
return createInjector(); return createInjector();

View File

@ -24,6 +24,7 @@ import {ComponentDefInternal, RenderFlags} from './interfaces/definition';
import {LElementNode, TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node'; import {LElementNode, 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, INJECTOR, LViewData, LViewFlags, RootContext, TVIEW} from './interfaces/view';
import {createElementRef} from './view_engine_compatibility';
import {RootViewRef, ViewRef} from './view_ref'; import {RootViewRef, ViewRef} from './view_ref';
export class ComponentFactoryResolver extends viewEngine_ComponentFactoryResolver { export class ComponentFactoryResolver extends viewEngine_ComponentFactoryResolver {
@ -176,8 +177,10 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
if (rendererFactory.end) rendererFactory.end(); if (rendererFactory.end) rendererFactory.end();
} }
const componentRef = const componentRef = new ComponentRef(
new ComponentRef(this.componentType, component, rootView, injector, hostNode !); this.componentType, component, rootView, injector,
createElementRef(viewEngine_ElementRef, tElementNode, rootView));
if (isInternalRootView) { if (isInternalRootView) {
// The host element of the internal root view is attached to the component's host view node // The host element of the internal root view is attached to the component's host view node
componentRef.hostView._tViewNode !.child = tElementNode; componentRef.hostView._tViewNode !.child = tElementNode;
@ -186,6 +189,19 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
} }
} }
const componentFactoryResolver: ComponentFactoryResolver = new ComponentFactoryResolver();
/**
* Creates a ComponentFactoryResolver and stores it on the injector. Or, if the
* ComponentFactoryResolver
* already exists, retrieves the existing ComponentFactoryResolver.
*
* @returns The ComponentFactoryResolver instance to use
*/
export function injectComponentFactoryResolver(): viewEngine_ComponentFactoryResolver {
return componentFactoryResolver;
}
/** /**
* Represents an instance of a Component created via a {@link ComponentFactory}. * Represents an instance of a Component created via a {@link ComponentFactory}.
* *
@ -196,7 +212,6 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
*/ */
export class ComponentRef<T> extends viewEngine_ComponentRef<T> { export class ComponentRef<T> extends viewEngine_ComponentRef<T> {
destroyCbs: (() => void)[]|null = []; destroyCbs: (() => void)[]|null = [];
location: viewEngine_ElementRef<any>;
injector: Injector; injector: Injector;
instance: T; instance: T;
hostView: ViewRef<T>; hostView: ViewRef<T>;
@ -205,13 +220,12 @@ export class ComponentRef<T> extends viewEngine_ComponentRef<T> {
constructor( constructor(
componentType: Type<T>, instance: T, rootView: LViewData, injector: Injector, componentType: Type<T>, instance: T, rootView: LViewData, injector: Injector,
hostNode: RElement) { public location: viewEngine_ElementRef) {
super(); super();
this.instance = instance; this.instance = instance;
this.hostView = this.changeDetectorRef = new RootViewRef<T>(rootView); this.hostView = this.changeDetectorRef = new RootViewRef<T>(rootView);
this.hostView._tViewNode = createNodeAtIndex(-1, TNodeType.View, null, null, null, rootView); this.hostView._tViewNode = createNodeAtIndex(-1, TNodeType.View, null, null, null, rootView);
this.injector = injector; this.injector = injector;
this.location = new viewEngine_ElementRef(hostNode);
this.componentType = componentType; this.componentType = componentType;
} }

View File

@ -9,44 +9,23 @@
// We are temporarily importing the existing viewEngine_from core so we can be sure we are // We are temporarily importing the existing viewEngine_from core so we can be sure we are
// correctly implementing its interfaces for backwards compatibility. // correctly implementing its interfaces for backwards compatibility.
import {ChangeDetectorRef as viewEngine_ChangeDetectorRef} from '../change_detection/change_detector_ref';
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, NullInjector, inject, setCurrentInjector} from '../di/injector'; import {InjectFlags, Injector, NullInjector, inject, setCurrentInjector} from '../di/injector';
import {ComponentFactory as viewEngine_ComponentFactory, ComponentRef as viewEngine_ComponentRef} from '../linker/component_factory';
import {ComponentFactoryResolver as viewEngine_ComponentFactoryResolver} from '../linker/component_factory_resolver';
import {ElementRef as viewEngine_ElementRef} from '../linker/element_ref';
import {NgModuleRef as viewEngine_NgModuleRef} from '../linker/ng_module_factory';
import {TemplateRef as viewEngine_TemplateRef} from '../linker/template_ref';
import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_container_ref';
import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_ViewRef} from '../linker/view_ref';
import {Renderer2} from '../render'; import {Renderer2} from '../render';
import {Type} from '../type'; import {Type} from '../type';
import {assertDefined, assertGreaterThan, assertLessThan} from './assert'; import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
import {ComponentFactoryResolver} from './component_ref';
import {getComponentDef, getDirectiveDef, getPipeDef} from './definition'; import {getComponentDef, getDirectiveDef, getPipeDef} from './definition';
import {_getViewData, addToViewTree, assertPreviousIsParent, createEmbeddedViewAndNode, createLContainer, createLNodeObject, createTNode, getPreviousOrParentNode, getPreviousOrParentTNode, getRenderer, loadElement, renderEmbeddedTemplate, resolveDirective} from './instructions'; import {NG_ELEMENT_ID} from './fields';
import {LContainer, RENDER_PARENT, VIEWS} from './interfaces/container'; import {_getViewData, addToViewTree, assertPreviousIsParent, createEmbeddedViewAndNode, createLContainer, createLNodeObject, createTNode, getPreviousOrParentNode, getPreviousOrParentTNode, getRenderer, loadElement, renderEmbeddedTemplate, resolveDirective, setEnvironment} from './instructions';
import {DirectiveDefInternal, RenderFlags} from './interfaces/definition'; import {DirectiveDefInternal, RenderFlags} from './interfaces/definition';
import {LInjector} from './interfaces/injector'; import {LInjector} from './interfaces/injector';
import {AttributeMarker, LContainerNode, LElementContainerNode, LElementNode, LNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode} from './interfaces/node'; import {AttributeMarker, LContainerNode, LElementContainerNode, LElementNode, LNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode} from './interfaces/node';
import {LQueries, QueryReadType} from './interfaces/query';
import {Renderer3, isProceduralRenderer} from './interfaces/renderer'; import {Renderer3, isProceduralRenderer} from './interfaces/renderer';
import {CONTEXT, DIRECTIVES, HOST_NODE, INJECTOR, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view'; import {CONTEXT, DIRECTIVES, HOST_NODE, INJECTOR, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert'; import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
import {addRemoveViewFromContainer, appendChild, detachView, findComponentView, getBeforeNodeForView, getHostElementNode, getParentLNode, getParentOrContainerNode, getRenderParent, insertView, removeView} from './node_manipulation'; import {addRemoveViewFromContainer, appendChild, detachView, findComponentView, getBeforeNodeForView, getHostElementNode, getParentLNode, getParentOrContainerNode, getRenderParent, insertView, removeView} from './node_manipulation';
import {getLNode, isComponent} from './util';
import {ViewRef} from './view_ref';
/**
* If a directive is diPublic, bloomAdd sets a property on the type with this constant as
* the key and the directive's unique ID as the value. This allows us to map directives to their
* bloom filter bit for DI.
*/
const NG_ELEMENT_ID = '__NG_ELEMENT_ID__';
/** /**
* 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
@ -196,56 +175,6 @@ export function directiveInject<T>(
return getOrCreateInjectable<T>(getOrCreateNodeInjector(), token, flags); return getOrCreateInjectable<T>(getOrCreateNodeInjector(), token, flags);
} }
/**
* Creates an ElementRef and stores it on the injector.
* Or, if the ElementRef already exists, retrieves the existing ElementRef.
*
* @returns The ElementRef instance to use
*/
export function injectElementRef(): viewEngine_ElementRef {
return createElementRef(getPreviousOrParentTNode(), _getViewData());
}
/**
* Creates a TemplateRef and stores it on the injector. Or, if the TemplateRef already
* exists, retrieves the existing TemplateRef.
*
* @returns The TemplateRef instance to use
*/
export function injectTemplateRef<T>(): viewEngine_TemplateRef<T> {
return createTemplateRef<T>(getPreviousOrParentTNode(), _getViewData());
}
/**
* Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef
* already exists, retrieves the existing ViewContainerRef.
*
* @returns The ViewContainerRef instance to use
*/
export function injectViewContainerRef(): viewEngine_ViewContainerRef {
const previousTNode =
getPreviousOrParentTNode() as TElementNode | TElementContainerNode | TContainerNode;
return createContainerRef(previousTNode, _getViewData());
}
/** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */
export function injectChangeDetectorRef(): viewEngine_ChangeDetectorRef {
return createViewRef(getPreviousOrParentTNode(), _getViewData(), null);
}
/**
* Creates a ComponentFactoryResolver and stores it on the injector. Or, if the
* ComponentFactoryResolver
* already exists, retrieves the existing ComponentFactoryResolver.
*
* @returns The ComponentFactoryResolver instance to use
*/
export function injectComponentFactoryResolver(): viewEngine_ComponentFactoryResolver {
return componentFactoryResolver;
}
const componentFactoryResolver: ComponentFactoryResolver = new ComponentFactoryResolver();
export function injectRenderer2(): Renderer2 { export function injectRenderer2(): Renderer2 {
return getOrCreateRenderer2(getOrCreateNodeInjector()); return getOrCreateRenderer2(getOrCreateNodeInjector());
} }
@ -298,27 +227,6 @@ export function injectAttribute(attrNameToInject: string): string|undefined {
return undefined; return undefined;
} }
/**
* Creates a ViewRef and stores it on the injector as ChangeDetectorRef (public alias).
*
* @param hostTNode The node that is requesting a ChangeDetectorRef
* @param hostView The view to which the node belongs
* @param context The context for this change detector ref
* @returns The ChangeDetectorRef to use
*/
export function createViewRef(
hostTNode: TNode, hostView: LViewData, context: any): viewEngine_ChangeDetectorRef {
if (isComponent(hostTNode)) {
const componentIndex = hostTNode.flags >> TNodeFlags.DirectiveStartingIndexShift;
const componentView = getLNode(hostTNode, hostView).data as LViewData;
return new ViewRef(componentView, context, componentIndex);
} else if (hostTNode.type === TNodeType.Element) {
const hostComponentView = findComponentView(hostView);
return new ViewRef(hostComponentView, hostComponentView[CONTEXT], -1);
}
return null !;
}
function getOrCreateRenderer2(di: LInjector): Renderer2 { function getOrCreateRenderer2(di: LInjector): Renderer2 {
const renderer = di.view[RENDERER]; const renderer = di.view[RENDERER];
if (isProceduralRenderer(renderer)) { if (isProceduralRenderer(renderer)) {
@ -342,11 +250,14 @@ function getOrCreateRenderer2(di: LInjector): Renderer2 {
export function getOrCreateInjectable<T>( export function getOrCreateInjectable<T>(
nodeInjector: LInjector, token: Type<T>| InjectionToken<T>, nodeInjector: LInjector, token: Type<T>| InjectionToken<T>,
flags: InjectFlags = InjectFlags.Default): T|null { flags: InjectFlags = InjectFlags.Default): T|null {
const bloomHash = bloomHashBit(token); const bloomHash = bloomHashBitOrFactory(token);
// 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.
if (typeof bloomHash === 'function') return bloomHash();
// If the token has a bloom hash, then it is a directive that is public to the injection system // If the token has a bloom hash, then it is a directive that is public to the injection system
// (diPublic) otherwise fall back to the module injector. // (diPublic) otherwise fall back to the module injector.
if (bloomHash !== null) { if (bloomHash != null) {
let injector: LInjector|null = nodeInjector; let injector: LInjector|null = nodeInjector;
while (injector) { while (injector) {
@ -433,9 +344,9 @@ function searchMatchesQueuedForCreation<T>(token: any, hostTView: TView): T|null
* @param token the injection token * @param token the injection token
* @returns the matching bit to check in the bloom filter or `null` if the token is not known. * @returns the matching bit to check in the bloom filter or `null` if the token is not known.
*/ */
function bloomHashBit(token: Type<any>| InjectionToken<any>): number|null { function bloomHashBitOrFactory(token: Type<any>| InjectionToken<any>): number|Function|undefined {
let id: number|undefined = (token as any)[NG_ELEMENT_ID]; const tokenId: number|undefined = (token as any)[NG_ELEMENT_ID] || null;
return typeof id === 'number' ? id & BLOOM_MASK : null; return typeof tokenId === 'number' ? tokenId & BLOOM_MASK : tokenId;
} }
/** /**
@ -525,258 +436,18 @@ function sameHostView(injector: LInjector): boolean {
return !!injector.parent && injector.parent.view === injector.view; return !!injector.parent && injector.parent.view === injector.view;
} }
export class ReadFromInjectorFn<T> {
constructor(readonly read: (tNode: TNode, view: LViewData, directiveIndex?: number) => T) {}
}
/**
* Creates an ElementRef for a given node injector and stores it on the injector.
*
* @param di The node injector where we should store a created ElementRef
* @returns The ElementRef instance to use
*/
export function createElementRef(tNode: TNode, view: LViewData): viewEngine_ElementRef {
return new ElementRef(getLNode(tNode, view).native);
}
export const QUERY_READ_TEMPLATE_REF = <QueryReadType<viewEngine_TemplateRef<any>>>(
new ReadFromInjectorFn<viewEngine_TemplateRef<any>>(
(tNode: TNode, view: LViewData) => { return createTemplateRef(tNode, view);}) as any);
export const QUERY_READ_CONTAINER_REF = <QueryReadType<viewEngine_ViewContainerRef>>(
new ReadFromInjectorFn<viewEngine_ViewContainerRef>(
(tNode: TNode, view: LViewData) => createContainerRef(
tNode as TElementNode | TContainerNode | TElementContainerNode, view)) as any);
export const QUERY_READ_ELEMENT_REF =
<QueryReadType<viewEngine_ElementRef>>(new ReadFromInjectorFn<viewEngine_ElementRef>(
(tNode: TNode, view: LViewData) => createElementRef(tNode, view)) as any);
export const QUERY_READ_FROM_NODE =
(new ReadFromInjectorFn<any>((tNode: TNode, view: LViewData, directiveIdx: number) => {
ngDevMode && assertNodeOfPossibleTypes(
tNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
if (directiveIdx > -1) {
return view[DIRECTIVES] ![directiveIdx];
}
if (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) {
return createElementRef(tNode, view);
}
if (tNode.type === TNodeType.Container) {
return createTemplateRef(tNode, view);
}
if (ngDevMode) {
// should never happen
throw new Error(`Unexpected node type: ${tNode.type}`);
}
}) as any as QueryReadType<any>);
/** A ref to a node's native element. */
class ElementRef extends viewEngine_ElementRef {}
/**
* Creates a ViewContainerRef and stores it on the injector.
*
* @param hostTNode The node that is requesting a ViewContainerRef
* @param hostView The view to which the node belongs
* @returns The ViewContainerRef instance to use
*/
export function createContainerRef(
hostTNode: TElementNode | TContainerNode | TElementContainerNode,
hostView: LViewData): viewEngine_ViewContainerRef {
const hostLNode = getLNode(hostTNode, hostView);
ngDevMode && assertNodeOfPossibleTypes(
hostTNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
const lContainer = createLContainer(hostView, true);
const comment = hostView[RENDERER].createComment(ngDevMode ? 'container' : '');
const lContainerNode: LContainerNode =
createLNodeObject(TNodeType.Container, hostLNode.nodeInjector, comment, lContainer);
lContainer[RENDER_PARENT] = getRenderParent(hostTNode, hostView);
appendChild(comment, hostTNode, hostView);
if (!hostTNode.dynamicContainerNode) {
hostTNode.dynamicContainerNode =
createTNode(TNodeType.Container, -1, null, null, hostTNode, null);
}
hostLNode.dynamicLContainerNode = lContainerNode;
addToViewTree(hostView, hostTNode.index as number, lContainer);
return new ViewContainerRef(
lContainer, hostTNode.dynamicContainerNode as TContainerNode, hostTNode, hostView);
}
export class NodeInjector implements Injector { export class NodeInjector implements Injector {
constructor(private _lInjector: LInjector) {} constructor(private _lInjector: LInjector) {}
get(token: any): any { get(token: any): any {
if (token === viewEngine_TemplateRef) {
return createTemplateRef(this._lInjector.tNode, this._lInjector.view);
}
if (token === viewEngine_ViewContainerRef) {
return createContainerRef(this._lInjector.tNode, this._lInjector.view);
}
if (token === viewEngine_ElementRef) {
return createElementRef(this._lInjector.tNode, this._lInjector.view);
}
if (token === viewEngine_ChangeDetectorRef) {
return createViewRef(this._lInjector.tNode, this._lInjector.view, null);
}
if (token === Renderer2) { if (token === Renderer2) {
return getOrCreateRenderer2(this._lInjector); return getOrCreateRenderer2(this._lInjector);
} }
setEnvironment(this._lInjector.tNode, this._lInjector.view);
return getOrCreateInjectable(this._lInjector, token); return getOrCreateInjectable(this._lInjector, token);
} }
} }
/**
* A ref to a container that enables adding and removing views from that container
* imperatively.
*/
class ViewContainerRef extends viewEngine_ViewContainerRef {
private _viewRefs: viewEngine_ViewRef[] = [];
constructor(
private _lContainer: LContainer, private _tContainerNode: TContainerNode,
private _hostTNode: TElementNode|TContainerNode|TElementContainerNode,
private _hostView: LViewData) {
super();
}
get element(): ElementRef {
// TODO: Remove LNode lookup when removing LNode.nodeInjector
const injector =
getOrCreateNodeInjectorForNode(this._getHostNode(), this._hostTNode, this._hostView);
return createElementRef(injector.tNode, injector.view);
}
get injector(): Injector {
// TODO: Remove LNode lookup when removing LNode.nodeInjector
const injector =
getOrCreateNodeInjectorForNode(this._getHostNode(), this._hostTNode, this._hostView);
return new NodeInjector(injector);
}
/** @deprecated No replacement */
get parentInjector(): Injector {
const parentLInjector = getParentLNode(this._hostTNode, this._hostView) !.nodeInjector;
return parentLInjector ? new NodeInjector(parentLInjector) : new NullInjector();
}
clear(): void {
while (this._lContainer[VIEWS].length) {
this.remove(0);
}
}
get(index: number): viewEngine_ViewRef|null { return this._viewRefs[index] || null; }
get length(): number { return this._lContainer[VIEWS].length; }
createEmbeddedView<C>(templateRef: viewEngine_TemplateRef<C>, context?: C, index?: number):
viewEngine_EmbeddedViewRef<C> {
const adjustedIdx = this._adjustIndex(index);
const viewRef = (templateRef as TemplateRef<C>)
.createEmbeddedView(
context || <any>{}, this._lContainer, this._tContainerNode,
this._hostView, adjustedIdx);
(viewRef as ViewRef<any>).attachToViewContainerRef(this);
this._viewRefs.splice(adjustedIdx, 0, viewRef);
return viewRef;
}
createComponent<C>(
componentFactory: viewEngine_ComponentFactory<C>, index?: number|undefined,
injector?: Injector|undefined, projectableNodes?: any[][]|undefined,
ngModuleRef?: viewEngine_NgModuleRef<any>|undefined): viewEngine_ComponentRef<C> {
const contextInjector = injector || this.parentInjector;
if (!ngModuleRef && contextInjector) {
ngModuleRef = contextInjector.get(viewEngine_NgModuleRef, null);
}
const componentRef =
componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
this.insert(componentRef.hostView, index);
return componentRef;
}
insert(viewRef: viewEngine_ViewRef, index?: number): viewEngine_ViewRef {
if (viewRef.destroyed) {
throw new Error('Cannot insert a destroyed View in a ViewContainer!');
}
const lView = (viewRef as ViewRef<any>)._view !;
const adjustedIdx = this._adjustIndex(index);
insertView(
lView, this._lContainer, this._hostView, adjustedIdx, this._tContainerNode.parent !.index);
const container = this._getHostNode().dynamicLContainerNode !;
const beforeNode = getBeforeNodeForView(adjustedIdx, this._lContainer[VIEWS], container);
addRemoveViewFromContainer(lView, true, beforeNode);
(viewRef as ViewRef<any>).attachToViewContainerRef(this);
this._viewRefs.splice(adjustedIdx, 0, viewRef);
return viewRef;
}
move(viewRef: viewEngine_ViewRef, newIndex: number): viewEngine_ViewRef {
const index = this.indexOf(viewRef);
this.detach(index);
this.insert(viewRef, this._adjustIndex(newIndex));
return viewRef;
}
indexOf(viewRef: viewEngine_ViewRef): number { return this._viewRefs.indexOf(viewRef); }
remove(index?: number): void {
const adjustedIdx = this._adjustIndex(index, -1);
removeView(this._lContainer, this._tContainerNode as TContainerNode, adjustedIdx);
this._viewRefs.splice(adjustedIdx, 1);
}
detach(index?: number): viewEngine_ViewRef|null {
const adjustedIdx = this._adjustIndex(index, -1);
detachView(this._lContainer, adjustedIdx, !!this._tContainerNode.detached);
return this._viewRefs.splice(adjustedIdx, 1)[0] || null;
}
private _adjustIndex(index?: number, shift: number = 0) {
if (index == null) {
return this._lContainer[VIEWS].length + shift;
}
if (ngDevMode) {
assertGreaterThan(index, -1, 'index must be positive');
// +1 because it's legal to insert at the end.
assertLessThan(index, this._lContainer[VIEWS].length + 1 + shift, 'index');
}
return index;
}
private _getHostNode() { return getLNode(this._hostTNode, this._hostView); }
}
/**
* Creates a TemplateRef and stores it on the injector.
*
* @param hostTNode The node that is requesting a TemplateRef
* @param hostView The view to which the node belongs
* @returns The TemplateRef instance to use
*/
export function createTemplateRef<T>(
hostTNode: TNode, hostView: LViewData): viewEngine_TemplateRef<T> {
const hostNode = getLNode(hostTNode, hostView);
ngDevMode && assertNodeType(hostTNode, TNodeType.Container);
ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
return new TemplateRef<any>(
hostView, createElementRef(hostTNode, hostView), hostTNode.tViews as TView, getRenderer(),
hostNode.data ![QUERIES]);
}
export function getFactoryOf<T>(type: Type<any>): ((type?: Type<T>) => T)|null { 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) ||
@ -800,33 +471,3 @@ export function getInheritedFactory<T>(type: Type<any>): (type: Type<T>) => T {
return (t) => new t(); return (t) => new t();
} }
} }
class TemplateRef<T> extends viewEngine_TemplateRef<T> {
constructor(
private _declarationParentView: LViewData, readonly elementRef: viewEngine_ElementRef,
private _tView: TView, private _renderer: Renderer3, private _queries: LQueries|null) {
super();
}
createEmbeddedView(
context: T, container?: LContainer, tContainerNode?: TContainerNode, hostView?: LViewData,
index?: number): viewEngine_EmbeddedViewRef<T> {
const lView = createEmbeddedViewAndNode(
this._tView, context, this._declarationParentView, this._renderer, this._queries);
if (container) {
insertView(lView, container, hostView !, index !, tContainerNode !.parent !.index);
}
renderEmbeddedTemplate(lView, this._tView, context, RenderFlags.Create);
const viewRef = new ViewRef(lView, context, -1);
viewRef._tViewNode = lView[HOST_NODE] as TViewNode;
return viewRef;
}
}
/**
* Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the
* `<ng-template>` element.
*/
export function templateRefExtractor(tNode: TContainerNode, currentView: LViewData) {
return createTemplateRef(tNode, currentView);
}

View File

@ -15,3 +15,10 @@ export const NG_INJECTOR_DEF = getClosureSafeProperty({ngInjectorDef: getClosure
export const NG_PIPE_DEF = getClosureSafeProperty({ngPipeDef: getClosureSafeProperty}); export const NG_PIPE_DEF = getClosureSafeProperty({ngPipeDef: getClosureSafeProperty});
export const NG_MODULE_DEF = getClosureSafeProperty({ngModuleDef: getClosureSafeProperty}); export const NG_MODULE_DEF = getClosureSafeProperty({ngModuleDef: getClosureSafeProperty});
export const NG_BASE_DEF = getClosureSafeProperty({ngBaseDef: getClosureSafeProperty}); export const NG_BASE_DEF = getClosureSafeProperty({ngBaseDef: getClosureSafeProperty});
/**
* If a directive is diPublic, bloomAdd sets a property on the type with this constant as
* the key and the directive's unique ID as the value. This allows us to map directives to their
* bloom filter bit for DI.
*/
export const NG_ELEMENT_ID = getClosureSafeProperty({__NG_ELEMENT_ID__: getClosureSafeProperty});

View File

@ -13,8 +13,8 @@ import {NgOnChangesFeature} from './features/ng_onchanges_feature';
import {PublicFeature} from './features/public_feature'; import {PublicFeature} from './features/public_feature';
import {BaseDef, ComponentDef, ComponentDefInternal, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveDefInternal, DirectiveType, PipeDef} from './interfaces/definition'; import {BaseDef, ComponentDef, ComponentDefInternal, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveDefInternal, DirectiveType, PipeDef} from './interfaces/definition';
export {ComponentFactory, ComponentFactoryResolver, ComponentRef, WRAP_RENDERER_FACTORY2} from './component_ref'; export {ComponentFactory, ComponentFactoryResolver, ComponentRef, WRAP_RENDERER_FACTORY2, injectComponentFactoryResolver} from './component_ref';
export {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, directiveInject, getFactoryOf, getInheritedFactory, injectAttribute, injectChangeDetectorRef, injectComponentFactoryResolver, injectElementRef, injectRenderer2, injectTemplateRef, injectViewContainerRef, templateRefExtractor} from './di'; export {directiveInject, getFactoryOf, getInheritedFactory, injectAttribute, injectRenderer2} from './di';
export {RenderFlags} from './interfaces/definition'; export {RenderFlags} from './interfaces/definition';
export {CssSelectorList} from './interfaces/projection'; export {CssSelectorList} from './interfaces/projection';
@ -119,6 +119,7 @@ export {
QueryList, QueryList,
query, query,
queryRefresh, queryRefresh,
QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF
} from './query'; } from './query';
export { export {
registerContentQuery, registerContentQuery,
@ -138,6 +139,8 @@ export {
pureFunctionV, pureFunctionV,
} from './pure_function'; } from './pure_function';
export {templateRefExtractor} from './view_engine_compatibility';
// clang-format on // clang-format on

View File

@ -30,7 +30,6 @@ import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector
import {StylingContext, allocStylingContext, createStylingContextTemplate, renderStyling as renderElementStyles, updateClassProp as updateElementClassProp, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling'; import {StylingContext, allocStylingContext, createStylingContextTemplate, renderStyling as renderElementStyles, updateClassProp as updateElementClassProp, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling';
import {assertDataInRangeInternal, getLNode, isContentQueryHost, isDifferent, loadElementInternal, loadInternal, stringify} from './util'; import {assertDataInRangeInternal, getLNode, isContentQueryHost, isDifferent, loadElementInternal, loadInternal, stringify} from './util';
/** /**
* A permanent marker promise which signifies that the current CD tree is * A permanent marker promise which signifies that the current CD tree is
* clean. * clean.
@ -138,6 +137,10 @@ export function getPreviousOrParentTNode(): TNode {
return previousOrParentTNode; return previousOrParentTNode;
} }
export function setEnvironment(tNode: TNode, view: LViewData) {
previousOrParentTNode = tNode;
viewData = view;
}
/** /**
* If `isParent` is: * If `isParent` is:

View File

@ -30,10 +30,6 @@ export const angularCoreEnv: {[name: string]: Function} = {
'ɵgetInheritedFactory': r3.getInheritedFactory, 'ɵgetInheritedFactory': r3.getInheritedFactory,
'inject': inject, 'inject': inject,
'ɵinjectAttribute': r3.injectAttribute, 'ɵinjectAttribute': r3.injectAttribute,
'ɵinjectChangeDetectorRef': r3.injectChangeDetectorRef,
'ɵinjectElementRef': r3.injectElementRef,
'ɵinjectTemplateRef': r3.injectTemplateRef,
'ɵinjectViewContainerRef': r3.injectViewContainerRef,
'ɵtemplateRefExtractor': r3.templateRefExtractor, 'ɵtemplateRefExtractor': r3.templateRefExtractor,
'ɵinjectRenderer2': r3.injectRenderer2, 'ɵinjectRenderer2': r3.injectRenderer2,
'ɵNgOnChangesFeature': r3.NgOnChangesFeature, 'ɵNgOnChangesFeature': r3.NgOnChangesFeature,

View File

@ -42,14 +42,8 @@ function reflectDependency(dep: any | any[]): R3DependencyMetadata {
}; };
function setTokenAndResolvedType(token: any): void { function setTokenAndResolvedType(token: any): void {
if (token === ElementRef) { if (token === Injector) {
meta.resolved = R3ResolvedDependencyType.ElementRef;
} else if (token === Injector) {
meta.resolved = R3ResolvedDependencyType.Injector; meta.resolved = R3ResolvedDependencyType.Injector;
} else if (token === TemplateRef) {
meta.resolved = R3ResolvedDependencyType.TemplateRef;
} else if (token === ViewContainerRef) {
meta.resolved = R3ResolvedDependencyType.ViewContainerRef;
} else { } else {
meta.resolved = R3ResolvedDependencyType.Token; meta.resolved = R3ResolvedDependencyType.Token;
} }

View File

@ -11,19 +11,23 @@
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {EventEmitter} from '../event_emitter'; import {EventEmitter} from '../event_emitter';
import {ElementRef as ViewEngine_ElementRef} from '../linker/element_ref';
import {QueryList as viewEngine_QueryList} from '../linker/query_list'; import {QueryList as viewEngine_QueryList} from '../linker/query_list';
import {TemplateRef as ViewEngine_TemplateRef} from '../linker/template_ref';
import {ViewContainerRef as ViewEngine_ViewContainerRef} from '../linker/view_container_ref';
import {Type} from '../type'; import {Type} from '../type';
import {getSymbolIterator} from '../util'; import {getSymbolIterator} from '../util';
import {assertDefined, assertEqual} from './assert'; import {assertDefined, assertEqual} from './assert';
import {ReadFromInjectorFn, getOrCreateNodeInjectorForNode} from './di';
import {_getViewData, assertPreviousIsParent, getOrCreateCurrentQueries, store, storeCleanupWithContext} from './instructions'; import {_getViewData, assertPreviousIsParent, getOrCreateCurrentQueries, store, storeCleanupWithContext} from './instructions';
import {DirectiveDefInternal, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition'; import {DirectiveDefInternal, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition';
import {LInjector, unusedValueExportToPlacateAjd as unused2} from './interfaces/injector'; import {LInjector, unusedValueExportToPlacateAjd as unused2} from './interfaces/injector';
import {LContainerNode, LElementNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, unusedValueExportToPlacateAjd as unused3} from './interfaces/node'; import {LContainerNode, LElementNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, unusedValueExportToPlacateAjd as unused3} from './interfaces/node';
import {LQueries, QueryReadType, unusedValueExportToPlacateAjd as unused4} from './interfaces/query'; import {LQueries, QueryReadType, unusedValueExportToPlacateAjd as unused4} from './interfaces/query';
import {DIRECTIVES, LViewData, TVIEW} from './interfaces/view'; import {DIRECTIVES, LViewData, TVIEW} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert';
import {flatten, getLNode, isContentQueryHost} from './util'; import {flatten, getLNode, isContentQueryHost} from './util';
import {createContainerRef, createElementRef, createTemplateRef} from './view_engine_compatibility';
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4; const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4;
@ -467,3 +471,63 @@ export function queryRefresh(queryList: QueryList<any>): boolean {
} }
return false; return false;
} }
export class ReadFromInjectorFn<T> {
constructor(readonly read: (tNode: TNode, view: LViewData, directiveIndex?: number) => T) {}
}
// TODO: Remove wrapper function with TemplateRef when we turn on Ivy
// Necessary for now to avoid a circular dependency
export const QUERY_READ_TEMPLATE_REF =
(TemplateRefConstructor: typeof ViewEngine_TemplateRef,
ElementRefConstructor: typeof ViewEngine_ElementRef) => {
return new ReadFromInjectorFn<ViewEngine_TemplateRef<any>>(
(tNode: TNode, view: LViewData) => {
return createTemplateRef(TemplateRefConstructor, ElementRefConstructor, tNode, view);
}) as any;
};
// TODO: Remove wrapper function with ViewContainerRef when we turn on Ivy
// Necessary for now to avoid a circular dependency
export const QUERY_READ_CONTAINER_REF =
(ViewContainerRefConstructor: typeof ViewEngine_ViewContainerRef,
ElementRefConstructor: typeof ViewEngine_ElementRef) => {
return <QueryReadType<ViewEngine_ViewContainerRef>>(
new ReadFromInjectorFn<ViewEngine_ViewContainerRef>(
(tNode: TNode, view: LViewData) => createContainerRef(
ViewContainerRefConstructor, ElementRefConstructor,
tNode as TElementNode | TContainerNode | TElementContainerNode, view)) as any);
};
// TODO: Remove wrapper function with ElementRef when we turn on Ivy
// Necessary for now to avoid a circular dependency
export const QUERY_READ_ELEMENT_REF = (ElementRefConstructor: typeof ViewEngine_ElementRef) => {
return <QueryReadType<ViewEngine_ElementRef>>(
new ReadFromInjectorFn<ViewEngine_ElementRef>((tNode: TNode, view: LViewData) => {
return createElementRef(ElementRefConstructor, tNode, view);
}) as any);
};
// TODO: Remove wrapper function with TemplateRef when we turn on Ivy
export const QUERY_READ_FROM_NODE =
(TemplateRefConstructor: typeof ViewEngine_TemplateRef,
ElementRefConstructor: typeof ViewEngine_ElementRef) => {
return new ReadFromInjectorFn<any>((tNode: TNode, view: LViewData, directiveIdx: number) => {
ngDevMode && assertNodeOfPossibleTypes(
tNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
if (directiveIdx > -1) {
return view[DIRECTIVES] ![directiveIdx];
}
if (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) {
return createElementRef(ElementRefConstructor, tNode, view);
}
if (tNode.type === TNodeType.Container) {
return createTemplateRef(TemplateRefConstructor, ElementRefConstructor, tNode, view);
}
if (ngDevMode) {
// should never happen
throw new Error(`Unexpected node type: ${tNode.type}`);
}
}) as any as QueryReadType<any>;
};

View File

@ -0,0 +1,351 @@
/**
* @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 {ChangeDetectorRef as ViewEngine_ChangeDetectorRef} from '../change_detection/change_detector_ref';
import {Injector, NullInjector} from '../di/injector';
import {ComponentFactory as viewEngine_ComponentFactory, ComponentRef as viewEngine_ComponentRef} from '../linker/component_factory';
import {ElementRef as ViewEngine_ElementRef} from '../linker/element_ref';
import {NgModuleRef as viewEngine_NgModuleRef} from '../linker/ng_module_factory';
import {TemplateRef as ViewEngine_TemplateRef} from '../linker/template_ref';
import {ViewContainerRef as ViewEngine_ViewContainerRef} from '../linker/view_container_ref';
import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_ViewRef} from '../linker/view_ref';
import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
import {NodeInjector, getOrCreateNodeInjectorForNode} from './di';
import {_getViewData, addToViewTree, createEmbeddedViewAndNode, createLContainer, createLNodeObject, createTNode, getPreviousOrParentTNode, getRenderer, renderEmbeddedTemplate} from './instructions';
import {LContainer, RENDER_PARENT, VIEWS} from './interfaces/container';
import {RenderFlags} from './interfaces/definition';
import {LContainerNode, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TViewNode} from './interfaces/node';
import {LQueries} from './interfaces/query';
import {RComment, RElement, Renderer3} from './interfaces/renderer';
import {CONTEXT, HOST_NODE, LViewData, QUERIES, RENDERER, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
import {addRemoveViewFromContainer, appendChild, detachView, findComponentView, getBeforeNodeForView, getParentLNode, getRenderParent, insertView, removeView} from './node_manipulation';
import {getLNode, isComponent} from './util';
import {ViewRef} from './view_ref';
/**
* Creates an ElementRef from the most recent node.
*
* @returns The ElementRef instance to use
*/
export function injectElementRef(ElementRefToken: typeof ViewEngine_ElementRef):
ViewEngine_ElementRef {
return createElementRef(ElementRefToken, getPreviousOrParentTNode(), _getViewData());
}
let R3ElementRef: {new (native: RElement | RComment): ViewEngine_ElementRef};
/**
* Creates an ElementRef given a node.
*
* @param ElementRefToken The ElementRef type
* @param tNode The node for which you'd like an ElementRef
* @param view The view to which the node belongs
* @returns The ElementRef instance to use
*/
export function createElementRef(
ElementRefToken: typeof ViewEngine_ElementRef, tNode: TNode,
view: LViewData): ViewEngine_ElementRef {
if (!R3ElementRef) {
// TODO: Fix class name, should be ElementRef, but there appears to be a rollup bug
R3ElementRef = class ElementRef_ extends ElementRefToken {};
}
return new R3ElementRef(getLNode(tNode, view).native);
}
let R3TemplateRef: {
new (
_declarationParentView: LViewData, elementRef: ViewEngine_ElementRef, _tView: TView,
_renderer: Renderer3, _queries: LQueries | null): ViewEngine_TemplateRef<any>
};
/**
* Creates a TemplateRef given a node.
*
* @returns The TemplateRef instance to use
*/
export function injectTemplateRef<T>(
TemplateRefToken: typeof ViewEngine_TemplateRef,
ElementRefToken: typeof ViewEngine_ElementRef): ViewEngine_TemplateRef<T> {
return createTemplateRef<T>(
TemplateRefToken, ElementRefToken, getPreviousOrParentTNode(), _getViewData());
}
/**
* Creates a TemplateRef and stores it on the injector.
*
* @param TemplateRefToken The TemplateRef type
* @param ElementRefToken The ElementRef type
* @param hostTNode The node that is requesting a TemplateRef
* @param hostView The view to which the node belongs
* @returns The TemplateRef instance to use
*/
export function createTemplateRef<T>(
TemplateRefToken: typeof ViewEngine_TemplateRef, ElementRefToken: typeof ViewEngine_ElementRef,
hostTNode: TNode, hostView: LViewData): ViewEngine_TemplateRef<T> {
if (!R3TemplateRef) {
// TODO: Fix class name, should be TemplateRef, but there appears to be a rollup bug
R3TemplateRef = class TemplateRef_<T> extends TemplateRefToken<T> {
constructor(
private _declarationParentView: LViewData, readonly elementRef: ViewEngine_ElementRef,
private _tView: TView, private _renderer: Renderer3, private _queries: LQueries|null) {
super();
}
createEmbeddedView(
context: T, container?: LContainer, tContainerNode?: TContainerNode, hostView?: LViewData,
index?: number): viewEngine_EmbeddedViewRef<T> {
const lView = createEmbeddedViewAndNode(
this._tView, context, this._declarationParentView, this._renderer, this._queries);
if (container) {
insertView(lView, container, hostView !, index !, tContainerNode !.parent !.index);
}
renderEmbeddedTemplate(lView, this._tView, context, RenderFlags.Create);
const viewRef = new ViewRef(lView, context, -1);
viewRef._tViewNode = lView[HOST_NODE] as TViewNode;
return viewRef;
}
};
}
const hostNode = getLNode(hostTNode, hostView);
ngDevMode && assertNodeType(hostTNode, TNodeType.Container);
ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
return new R3TemplateRef(
hostView, createElementRef(ElementRefToken, hostTNode, hostView), hostTNode.tViews as TView,
getRenderer(), hostNode.data ![QUERIES]);
}
/**
* Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the
* `<ng-template>` element.
*/
export function templateRefExtractor(
TemplateRefToken: typeof ViewEngine_TemplateRef,
ElementRefToken: typeof ViewEngine_ElementRef) {
return (tNode: TNode, currentView: LViewData) => {
return createTemplateRef(TemplateRefToken, ElementRefToken, tNode, currentView);
};
}
let R3ViewContainerRef: {
new (
lContainer: LContainer, tContainerNode: TContainerNode,
hostTNode: TElementNode | TContainerNode | TElementContainerNode, hostView: LViewData):
ViewEngine_ViewContainerRef
};
/**
* Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef
* already exists, retrieves the existing ViewContainerRef.
*
* @returns The ViewContainerRef instance to use
*/
export function injectViewContainerRef(
ViewContainerRefToken: typeof ViewEngine_ViewContainerRef,
ElementRefToken: typeof ViewEngine_ElementRef): ViewEngine_ViewContainerRef {
const previousTNode =
getPreviousOrParentTNode() as TElementNode | TElementContainerNode | TContainerNode;
return createContainerRef(ViewContainerRefToken, ElementRefToken, previousTNode, _getViewData());
}
/**
* Creates a ViewContainerRef and stores it on the injector.
*
* @param ViewContainerRefToken The ViewContainerRef type
* @param ElementRefToken The ElementRef type
* @param hostTNode The node that is requesting a ViewContainerRef
* @param hostView The view to which the node belongs
* @returns The ViewContainerRef instance to use
*/
export function createContainerRef(
ViewContainerRefToken: typeof ViewEngine_ViewContainerRef,
ElementRefToken: typeof ViewEngine_ElementRef,
hostTNode: TElementNode|TContainerNode|TElementContainerNode,
hostView: LViewData): ViewEngine_ViewContainerRef {
if (!R3ViewContainerRef) {
// TODO: Fix class name, should be ViewContainerRef, but there appears to be a rollup bug
R3ViewContainerRef = class ViewContainerRef_ extends ViewContainerRefToken {
private _viewRefs: viewEngine_ViewRef[] = [];
constructor(
private _lContainer: LContainer, private _tContainerNode: TContainerNode,
private _hostTNode: TElementNode|TContainerNode|TElementContainerNode,
private _hostView: LViewData) {
super();
}
get element(): ViewEngine_ElementRef {
return createElementRef(ElementRefToken, this._hostTNode, this._hostView);
}
get injector(): Injector {
// TODO: Remove LNode lookup when removing LNode.nodeInjector
const injector =
getOrCreateNodeInjectorForNode(this._getHostNode(), this._hostTNode, this._hostView);
return new NodeInjector(injector);
}
/** @deprecated No replacement */
get parentInjector(): Injector {
const parentLInjector = getParentLNode(this._hostTNode, this._hostView) !.nodeInjector;
return parentLInjector ? new NodeInjector(parentLInjector) : new NullInjector();
}
clear(): void {
while (this._lContainer[VIEWS].length) {
this.remove(0);
}
}
get(index: number): viewEngine_ViewRef|null { return this._viewRefs[index] || null; }
get length(): number { return this._lContainer[VIEWS].length; }
createEmbeddedView<C>(templateRef: ViewEngine_TemplateRef<C>, context?: C, index?: number):
viewEngine_EmbeddedViewRef<C> {
const adjustedIdx = this._adjustIndex(index);
const viewRef = (templateRef as any)
.createEmbeddedView(
context || <any>{}, this._lContainer, this._tContainerNode,
this._hostView, adjustedIdx);
(viewRef as ViewRef<any>).attachToViewContainerRef(this);
this._viewRefs.splice(adjustedIdx, 0, viewRef);
return viewRef;
}
createComponent<C>(
componentFactory: viewEngine_ComponentFactory<C>, index?: number|undefined,
injector?: Injector|undefined, projectableNodes?: any[][]|undefined,
ngModuleRef?: viewEngine_NgModuleRef<any>|undefined): viewEngine_ComponentRef<C> {
const contextInjector = injector || this.parentInjector;
if (!ngModuleRef && contextInjector) {
ngModuleRef = contextInjector.get(viewEngine_NgModuleRef, null);
}
const componentRef =
componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
this.insert(componentRef.hostView, index);
return componentRef;
}
insert(viewRef: viewEngine_ViewRef, index?: number): viewEngine_ViewRef {
if (viewRef.destroyed) {
throw new Error('Cannot insert a destroyed View in a ViewContainer!');
}
const lView = (viewRef as ViewRef<any>)._view !;
const adjustedIdx = this._adjustIndex(index);
insertView(
lView, this._lContainer, this._hostView, adjustedIdx,
this._tContainerNode.parent !.index);
const container = this._getHostNode().dynamicLContainerNode !;
const beforeNode = getBeforeNodeForView(adjustedIdx, this._lContainer[VIEWS], container);
addRemoveViewFromContainer(lView, true, beforeNode);
(viewRef as ViewRef<any>).attachToViewContainerRef(this);
this._viewRefs.splice(adjustedIdx, 0, viewRef);
return viewRef;
}
move(viewRef: viewEngine_ViewRef, newIndex: number): viewEngine_ViewRef {
const index = this.indexOf(viewRef);
this.detach(index);
this.insert(viewRef, this._adjustIndex(newIndex));
return viewRef;
}
indexOf(viewRef: viewEngine_ViewRef): number { return this._viewRefs.indexOf(viewRef); }
remove(index?: number): void {
const adjustedIdx = this._adjustIndex(index, -1);
removeView(this._lContainer, this._tContainerNode as TContainerNode, adjustedIdx);
this._viewRefs.splice(adjustedIdx, 1);
}
detach(index?: number): viewEngine_ViewRef|null {
const adjustedIdx = this._adjustIndex(index, -1);
detachView(this._lContainer, adjustedIdx, !!this._tContainerNode.detached);
return this._viewRefs.splice(adjustedIdx, 1)[0] || null;
}
private _adjustIndex(index?: number, shift: number = 0) {
if (index == null) {
return this._lContainer[VIEWS].length + shift;
}
if (ngDevMode) {
assertGreaterThan(index, -1, 'index must be positive');
// +1 because it's legal to insert at the end.
assertLessThan(index, this._lContainer[VIEWS].length + 1 + shift, 'index');
}
return index;
}
private _getHostNode() { return getLNode(this._hostTNode, this._hostView); }
};
}
const hostLNode = getLNode(hostTNode, hostView);
ngDevMode && assertNodeOfPossibleTypes(
hostTNode, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
const lContainer = createLContainer(hostView, true);
const comment = hostView[RENDERER].createComment(ngDevMode ? 'container' : '');
const lContainerNode: LContainerNode =
createLNodeObject(TNodeType.Container, hostLNode.nodeInjector, comment, lContainer);
lContainer[RENDER_PARENT] = getRenderParent(hostTNode, hostView);
appendChild(comment, hostTNode, hostView);
if (!hostTNode.dynamicContainerNode) {
hostTNode.dynamicContainerNode =
createTNode(TNodeType.Container, -1, null, null, hostTNode, null);
}
hostLNode.dynamicLContainerNode = lContainerNode;
addToViewTree(hostView, hostTNode.index as number, lContainer);
return new R3ViewContainerRef(
lContainer, hostTNode.dynamicContainerNode as TContainerNode, hostTNode, hostView);
}
/** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */
export function injectChangeDetectorRef(): ViewEngine_ChangeDetectorRef {
return createViewRef(getPreviousOrParentTNode(), _getViewData(), null);
}
/**
* Creates a ViewRef and stores it on the injector as ChangeDetectorRef (public alias).
*
* @param hostTNode The node that is requesting a ChangeDetectorRef
* @param hostView The view to which the node belongs
* @param context The context for this change detector ref
* @returns The ChangeDetectorRef to use
*/
export function createViewRef(
hostTNode: TNode, hostView: LViewData, context: any): ViewEngine_ChangeDetectorRef {
if (isComponent(hostTNode)) {
const componentIndex = hostTNode.flags >> TNodeFlags.DirectiveStartingIndexShift;
const componentView = getLNode(hostTNode, hostView).data as LViewData;
return new ViewRef(componentView, context, componentIndex);
} else if (hostTNode.type === TNodeType.Element) {
const hostComponentView = findComponentView(hostView);
return new ViewRef(hostComponentView, hostComponentView[CONTEXT], -1);
}
return null !;
}

View File

@ -32,9 +32,6 @@
{ {
"name": "ChangeDetectionStrategy" "name": "ChangeDetectionStrategy"
}, },
{
"name": "ChangeDetectorRef"
},
{ {
"name": "CorePlayerHandler" "name": "CorePlayerHandler"
}, },
@ -65,9 +62,6 @@
{ {
"name": "ElementRef" "name": "ElementRef"
}, },
{
"name": "ElementRef$1"
},
{ {
"name": "FLAGS" "name": "FLAGS"
}, },
@ -146,6 +140,15 @@
{ {
"name": "QUERIES" "name": "QUERIES"
}, },
{
"name": "R3_ELEMENT_REF_FACTORY"
},
{
"name": "R3_TEMPLATE_REF_FACTORY"
},
{
"name": "R3_VIEW_CONTAINER_REF_FACTORY"
},
{ {
"name": "RENDERER" "name": "RENDERER"
}, },
@ -179,18 +182,12 @@
{ {
"name": "TemplateRef" "name": "TemplateRef"
}, },
{
"name": "TemplateRef$1"
},
{ {
"name": "VIEWS" "name": "VIEWS"
}, },
{ {
"name": "ViewContainerRef" "name": "ViewContainerRef"
}, },
{
"name": "ViewContainerRef$1"
},
{ {
"name": "ViewEncapsulation$1" "name": "ViewEncapsulation$1"
}, },
@ -300,7 +297,7 @@
"name": "bloomFindPossibleInjector" "name": "bloomFindPossibleInjector"
}, },
{ {
"name": "bloomHashBit" "name": "bloomHashBitOrFactory"
}, },
{ {
"name": "buildAnimationPlayer" "name": "buildAnimationPlayer"
@ -401,9 +398,6 @@
{ {
"name": "createViewQuery" "name": "createViewQuery"
}, },
{
"name": "createViewRef"
},
{ {
"name": "defineComponent" "name": "defineComponent"
}, },
@ -719,9 +713,6 @@
{ {
"name": "isClassBased" "name": "isClassBased"
}, },
{
"name": "isComponent"
},
{ {
"name": "isComponentInstance" "name": "isComponentInstance"
}, },
@ -926,6 +917,9 @@
{ {
"name": "setDirty" "name": "setDirty"
}, },
{
"name": "setEnvironment"
},
{ {
"name": "setFlag" "name": "setFlag"
}, },

View File

@ -1238,9 +1238,21 @@
{ {
"name": "Quote" "name": "Quote"
}, },
{
"name": "R3_CHANGE_DETECTOR_REF_FACTORY$1"
},
{ {
"name": "R3_COMPILE_INJECTABLE$1" "name": "R3_COMPILE_INJECTABLE$1"
}, },
{
"name": "R3_ELEMENT_REF_FACTORY$1"
},
{
"name": "R3_TEMPLATE_REF_FACTORY$1"
},
{
"name": "R3_VIEW_CONTAINER_REF_FACTORY$1"
},
{ {
"name": "ReadKeyExpr" "name": "ReadKeyExpr"
}, },
@ -3389,6 +3401,9 @@
{ {
"name": "noop$3" "name": "noop$3"
}, },
{
"name": "noopFactory"
},
{ {
"name": "noopScope" "name": "noopScope"
}, },

View File

@ -26,9 +26,6 @@
{ {
"name": "ChangeDetectionStrategy" "name": "ChangeDetectionStrategy"
}, },
{
"name": "ChangeDetectorRef"
},
{ {
"name": "DECLARATION_VIEW" "name": "DECLARATION_VIEW"
}, },
@ -50,9 +47,6 @@
{ {
"name": "ElementRef" "name": "ElementRef"
}, },
{
"name": "ElementRef$1"
},
{ {
"name": "FLAGS" "name": "FLAGS"
}, },
@ -137,6 +131,15 @@
{ {
"name": "QUERIES" "name": "QUERIES"
}, },
{
"name": "R3_ELEMENT_REF_FACTORY"
},
{
"name": "R3_TEMPLATE_REF_FACTORY"
},
{
"name": "R3_VIEW_CONTAINER_REF_FACTORY"
},
{ {
"name": "RENDERER" "name": "RENDERER"
}, },
@ -167,9 +170,6 @@
{ {
"name": "TemplateRef" "name": "TemplateRef"
}, },
{
"name": "TemplateRef$1"
},
{ {
"name": "ToDoAppComponent_footer_Template_6" "name": "ToDoAppComponent_footer_Template_6"
}, },
@ -200,9 +200,6 @@
{ {
"name": "ViewContainerRef" "name": "ViewContainerRef"
}, },
{
"name": "ViewContainerRef$1"
},
{ {
"name": "ViewEncapsulation$1" "name": "ViewEncapsulation$1"
}, },
@ -366,7 +363,7 @@
"name": "bloomFindPossibleInjector" "name": "bloomFindPossibleInjector"
}, },
{ {
"name": "bloomHashBit" "name": "bloomHashBitOrFactory"
}, },
{ {
"name": "cacheMatchingDirectivesForNode" "name": "cacheMatchingDirectivesForNode"
@ -464,9 +461,6 @@
{ {
"name": "createViewQuery" "name": "createViewQuery"
}, },
{
"name": "createViewRef"
},
{ {
"name": "defineComponent" "name": "defineComponent"
}, },
@ -722,6 +716,9 @@
{ {
"name": "inject" "name": "inject"
}, },
{
"name": "injectElementRef"
},
{ {
"name": "injectTemplateRef" "name": "injectTemplateRef"
}, },
@ -740,9 +737,6 @@
{ {
"name": "invertObject" "name": "invertObject"
}, },
{
"name": "isComponent"
},
{ {
"name": "isContentQueryHost" "name": "isContentQueryHost"
}, },
@ -944,6 +938,9 @@
{ {
"name": "setDirty" "name": "setDirty"
}, },
{
"name": "setEnvironment"
},
{ {
"name": "setFlag" "name": "setFlag"
}, },

View File

@ -281,9 +281,6 @@
{ {
"name": "ElementRef" "name": "ElementRef"
}, },
{
"name": "ElementRef$1"
},
{ {
"name": "EmulatedEncapsulationDomRenderer2" "name": "EmulatedEncapsulationDomRenderer2"
}, },
@ -662,6 +659,18 @@
{ {
"name": "R3Injector" "name": "R3Injector"
}, },
{
"name": "R3_CHANGE_DETECTOR_REF_FACTORY"
},
{
"name": "R3_ELEMENT_REF_FACTORY"
},
{
"name": "R3_TEMPLATE_REF_FACTORY"
},
{
"name": "R3_VIEW_CONTAINER_REF_FACTORY"
},
{ {
"name": "REMOVE_EVENT_LISTENER" "name": "REMOVE_EVENT_LISTENER"
}, },
@ -809,9 +818,6 @@
{ {
"name": "TemplateRef" "name": "TemplateRef"
}, },
{
"name": "TemplateRef$1"
},
{ {
"name": "Testability" "name": "Testability"
}, },
@ -890,9 +896,6 @@
{ {
"name": "ViewContainerRef" "name": "ViewContainerRef"
}, },
{
"name": "ViewContainerRef$1"
},
{ {
"name": "ViewEncapsulation$1" "name": "ViewEncapsulation$1"
}, },
@ -1200,7 +1203,7 @@
"name": "bloomFindPossibleInjector" "name": "bloomFindPossibleInjector"
}, },
{ {
"name": "bloomHashBit" "name": "bloomHashBitOrFactory"
}, },
{ {
"name": "cacheMatchingDirectivesForNode" "name": "cacheMatchingDirectivesForNode"
@ -2288,6 +2291,9 @@
{ {
"name": "setDirty" "name": "setDirty"
}, },
{
"name": "setEnvironment"
},
{ {
"name": "setFlag" "name": "setFlag"
}, },

View File

@ -5,7 +5,9 @@
* Use of this source code is governed by an MIT-style license that can be * 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 * found in the LICENSE file at https://angular.io/license
*/ */
import {ElementRef, TemplateRef} from '@angular/core';
import {RenderFlags} from '@angular/core/src/render3'; import {RenderFlags} from '@angular/core/src/render3';
import {AnimationContext, PlayState, Player, PlayerHandler} from '../../../src/render3/animations/interfaces'; import {AnimationContext, PlayState, Player, PlayerHandler} from '../../../src/render3/animations/interfaces';
import {addPlayer, getOrCreateAnimationContext, getPlayers} from '../../../src/render3/animations/players'; import {addPlayer, getOrCreateAnimationContext, getPlayers} from '../../../src/render3/animations/players';
import {QUERY_READ_FROM_NODE, defineComponent, getHostElement} from '../../../src/render3/index'; import {QUERY_READ_FROM_NODE, defineComponent, getHostElement} from '../../../src/render3/index';
@ -13,6 +15,7 @@ import {element, elementEnd, elementStart, elementStyling, elementStylingApply,
import {RElement} from '../../../src/render3/interfaces/renderer'; import {RElement} from '../../../src/render3/interfaces/renderer';
import {QueryList, query, queryRefresh} from '../../../src/render3/query'; import {QueryList, query, queryRefresh} from '../../../src/render3/query';
import {ComponentFixture} from '../render_util'; import {ComponentFixture} from '../render_util';
import {MockPlayer} from './mock_player'; import {MockPlayer} from './mock_player';
describe('animation player access', () => { describe('animation player access', () => {
@ -286,7 +289,7 @@ class SuperComp {
}, },
viewQuery: function(rf: RenderFlags, ctx: SuperComp) { viewQuery: function(rf: RenderFlags, ctx: SuperComp) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['child'], true, QUERY_READ_FROM_NODE); query(0, ['child'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;

View File

@ -10,7 +10,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 {LifecycleHooksFeature, defineComponent, defineDirective, injectChangeDetectorRef} from '../../src/render3/index'; import {directiveInject} from '../../src/render3/di';
import {LifecycleHooksFeature, defineComponent, defineDirective} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, detectChanges, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, listener, markDirty, text, textBinding, tick} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, detectChanges, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, listener, markDirty, text, 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';
@ -18,7 +19,6 @@ import {RElement, Renderer3, RendererFactory3} from '../../src/render3/interface
import {containerEl, createComponent, renderComponent, requestAnimationFrame} from './render_util'; import {containerEl, createComponent, renderComponent, requestAnimationFrame} from './render_util';
describe('change detection', () => { describe('change detection', () => {
describe('markDirty, detectChanges, whenRendered, getRenderedText', () => { describe('markDirty, detectChanges, whenRendered, getRenderedText', () => {
class MyComponent implements DoCheck { class MyComponent implements DoCheck {
value: string = 'works'; value: string = 'works';
@ -326,7 +326,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: MyComp, type: MyComp,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: () => myComp = new MyComp(injectChangeDetectorRef()), factory: () => myComp = new MyComp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 1, vars: 1,
/** {{ name }} */ /** {{ name }} */
@ -352,7 +352,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: ParentComp, type: ParentComp,
selectors: [['parent-comp']], selectors: [['parent-comp']],
factory: () => new ParentComp(injectChangeDetectorRef()), factory: () => new ParentComp(directiveInject(ChangeDetectorRef as any)),
consts: 2, consts: 2,
vars: 1, vars: 1,
/** /**
@ -378,7 +378,7 @@ describe('change detection', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
type: Dir, type: Dir,
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
factory: () => dir = new Dir(injectChangeDetectorRef()) factory: () => dir = new Dir(directiveInject(ChangeDetectorRef as any))
}); });
} }
@ -487,7 +487,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()), factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
consts: 2, consts: 2,
vars: 1, vars: 1,
/** /**
@ -542,7 +542,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: DetectChangesComp, type: DetectChangesComp,
selectors: [['detect-changes-comp']], selectors: [['detect-changes-comp']],
factory: () => new DetectChangesComp(injectChangeDetectorRef()), factory: () => new DetectChangesComp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 1, vars: 1,
/** {{ value }} */ /** {{ value }} */
@ -575,7 +575,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: DetectChangesComp, type: DetectChangesComp,
selectors: [['detect-changes-comp']], selectors: [['detect-changes-comp']],
factory: () => new DetectChangesComp(injectChangeDetectorRef()), factory: () => new DetectChangesComp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 1, vars: 1,
/** {{ doCheckCount }} */ /** {{ doCheckCount }} */
@ -605,7 +605,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()), factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 0, vars: 0,
/** <detached-comp></detached-comp> */ /** <detached-comp></detached-comp> */
@ -629,7 +629,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: DetachedComp, type: DetachedComp,
selectors: [['detached-comp']], selectors: [['detached-comp']],
factory: () => comp = new DetachedComp(injectChangeDetectorRef()), factory: () => comp = new DetachedComp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 1, vars: 1,
/** {{ value }} */ /** {{ value }} */
@ -730,7 +730,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: OnPushComp, type: OnPushComp,
selectors: [['on-push-comp']], selectors: [['on-push-comp']],
factory: () => onPushComp = new OnPushComp(injectChangeDetectorRef()), factory: () => onPushComp = new OnPushComp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 1, vars: 1,
/** {{ value }} */ /** {{ value }} */
@ -791,7 +791,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: OnPushComp, type: OnPushComp,
selectors: [['on-push-comp']], selectors: [['on-push-comp']],
factory: () => comp = new OnPushComp(injectChangeDetectorRef()), factory: () => comp = new OnPushComp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 1, vars: 1,
/** {{ value }} */ /** {{ value }} */
@ -960,7 +960,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: NoChangesComp, type: NoChangesComp,
selectors: [['no-changes-comp']], selectors: [['no-changes-comp']],
factory: () => comp = new NoChangesComp(injectChangeDetectorRef()), factory: () => comp = new NoChangesComp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 1, vars: 1,
template: (rf: RenderFlags, ctx: NoChangesComp) => { template: (rf: RenderFlags, ctx: NoChangesComp) => {
@ -982,7 +982,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: AppComp, type: AppComp,
selectors: [['app-comp']], selectors: [['app-comp']],
factory: () => new AppComp(injectChangeDetectorRef()), factory: () => new AppComp(directiveInject(ChangeDetectorRef as any)),
consts: 2, consts: 2,
vars: 1, vars: 1,
/** /**
@ -1045,7 +1045,7 @@ describe('change detection', () => {
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: EmbeddedViewApp, type: EmbeddedViewApp,
selectors: [['embedded-view-app']], selectors: [['embedded-view-app']],
factory: () => new EmbeddedViewApp(injectChangeDetectorRef()), factory: () => new EmbeddedViewApp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 0, vars: 0,
/** /**

View File

@ -7,6 +7,7 @@
*/ */
import {NgForOfContext} from '@angular/common'; import {NgForOfContext} from '@angular/common';
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, getCurrentView, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, restoreView, text, textBinding, elementContainerStart, elementContainerEnd, reference} from '../../src/render3/instructions';
@ -896,11 +897,15 @@ describe('@angular/common integration', () => {
*/ */
template: (rf: RenderFlags, myApp: MyApp) => { template: (rf: RenderFlags, myApp: MyApp) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template(0, (rf1: RenderFlags) => { template(
if (rf1 & RenderFlags.Create) { 0,
text(0, 'from tpl'); (rf1: RenderFlags) => {
} if (rf1 & RenderFlags.Create) {
}, 1, 0, undefined, undefined, ['tpl', ''], templateRefExtractor); text(0, 'from tpl');
}
},
1, 0, undefined, undefined, ['tpl', ''],
templateRefExtractor(TemplateRef, ElementRef));
template(2, null, 0, 0, null, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']); template(2, null, 0, 0, null, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']);
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
@ -939,11 +944,15 @@ describe('@angular/common integration', () => {
*/ */
template: (rf: RenderFlags, myApp: MyApp) => { template: (rf: RenderFlags, myApp: MyApp) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template(0, (rf1: RenderFlags) => { template(
if (rf1 & RenderFlags.Create) { 0,
text(0, 'from tpl'); (rf1: RenderFlags) => {
} if (rf1 & RenderFlags.Create) {
}, 1, 0, undefined, undefined, ['tpl', ''], templateRefExtractor); text(0, 'from tpl');
}
},
1, 0, undefined, undefined, ['tpl', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementContainerStart(2, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']); elementContainerStart(2, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']);
elementContainerEnd(); elementContainerEnd();
} }

View File

@ -7,9 +7,9 @@
*/ */
import {NgForOf as NgForOfDef, NgIf as NgIfDef, NgTemplateOutlet as NgTemplateOutletDef} from '@angular/common'; import {NgForOf as NgForOfDef, NgIf as NgIfDef, NgTemplateOutlet as NgTemplateOutletDef} from '@angular/common';
import {IterableDiffers} from '@angular/core'; import {IterableDiffers, TemplateRef, ViewContainerRef} from '@angular/core';
import {DirectiveType, NgOnChangesFeature, defineDirective, directiveInject, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index'; import {DirectiveType, NgOnChangesFeature, defineDirective, directiveInject} from '../../src/render3/index';
export const NgForOf: DirectiveType<NgForOfDef<any>> = NgForOfDef as any; export const NgForOf: DirectiveType<NgForOfDef<any>> = NgForOfDef as any;
export const NgIf: DirectiveType<NgIfDef> = NgIfDef as any; export const NgIf: DirectiveType<NgIfDef> = NgIfDef as any;
@ -19,7 +19,8 @@ NgForOf.ngDirectiveDef = defineDirective({
type: NgForOfDef, type: NgForOfDef,
selectors: [['', 'ngForOf', '']], selectors: [['', 'ngForOf', '']],
factory: () => new NgForOfDef( factory: () => new NgForOfDef(
injectViewContainerRef(), injectTemplateRef(), directiveInject(IterableDiffers)), directiveInject(ViewContainerRef as any), directiveInject(TemplateRef as any),
directiveInject(IterableDiffers)),
inputs: { inputs: {
ngForOf: 'ngForOf', ngForOf: 'ngForOf',
ngForTrackBy: 'ngForTrackBy', ngForTrackBy: 'ngForTrackBy',
@ -30,14 +31,15 @@ NgForOf.ngDirectiveDef = defineDirective({
(NgIf as any).ngDirectiveDef = defineDirective({ (NgIf as any).ngDirectiveDef = defineDirective({
type: NgIfDef, type: NgIfDef,
selectors: [['', 'ngIf', '']], selectors: [['', 'ngIf', '']],
factory: () => new NgIfDef(injectViewContainerRef(), injectTemplateRef()), factory: () => new NgIfDef(
directiveInject(ViewContainerRef as any), directiveInject(TemplateRef as any)),
inputs: {ngIf: 'ngIf', ngIfThen: 'ngIfThen', ngIfElse: 'ngIfElse'} inputs: {ngIf: 'ngIf', ngIfThen: 'ngIfThen', ngIfElse: 'ngIfElse'}
}); });
(NgTemplateOutlet as any).ngDirectiveDef = defineDirective({ (NgTemplateOutlet as any).ngDirectiveDef = defineDirective({
type: NgTemplateOutletDef, type: NgTemplateOutletDef,
selectors: [['', 'ngTemplateOutlet', '']], selectors: [['', 'ngTemplateOutlet', '']],
factory: () => new NgTemplateOutletDef(injectViewContainerRef()), factory: () => new NgTemplateOutletDef(directiveInject(ViewContainerRef as any)),
features: [NgOnChangesFeature], features: [NgOnChangesFeature],
inputs: inputs:
{ngTemplateOutlet: 'ngTemplateOutlet', ngTemplateOutletContext: 'ngTemplateOutletContext'} {ngTemplateOutlet: 'ngTemplateOutlet', ngTemplateOutletContext: 'ngTemplateOutletContext'}

View File

@ -394,7 +394,7 @@ describe('components & directives', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: IfDirective, type: IfDirective,
selectors: [['', 'if', '']], selectors: [['', 'if', '']],
factory: () => new IfDirective($r3$.ɵinjectTemplateRef()), factory: () => new IfDirective($r3$.ɵdirectiveInject(TemplateRef as any)),
}); });
// /NORMATIVE // /NORMATIVE
} }

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 {Attribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, Injector, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, SkipSelf, TemplateRef, ViewChild, ViewChildren, ViewContainerRef, defineInjectable, defineInjector, 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 {renderComponent, toHtml} from '../render_util'; import {renderComponent, toHtml} from '../render_util';
@ -32,7 +32,7 @@ describe('injection', () => {
type: MyComp, type: MyComp,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: function MyComp_Factory() { factory: function MyComp_Factory() {
return new MyComp($r3$.ɵinjectChangeDetectorRef()); return new MyComp($r3$.ɵdirectiveInject(ChangeDetectorRef as any));
}, },
consts: 1, consts: 1,
vars: 1, vars: 1,

View File

@ -6,10 +6,13 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {ElementRef, TemplateRef} from '@angular/core';
import {Component} from '../../../src/core'; import {Component} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export'; import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentFixture} from '../render_util'; import {ComponentFixture} from '../render_util';
/// See: `normative.md` /// See: `normative.md`
describe('local references', () => { describe('local references', () => {
type $RenderFlags$ = $r3$.ɵRenderFlags; type $RenderFlags$ = $r3$.ɵRenderFlags;
@ -69,7 +72,7 @@ describe('local references', () => {
if (rf & 1) { if (rf & 1) {
$r3$.ɵtemplate( $r3$.ɵtemplate(
0, MyComponent_Template_0, 0, 0, null, null, ['tpl', ''], 0, MyComponent_Template_0, 0, 0, null, null, ['tpl', ''],
$r3$.ɵtemplateRefExtractor); $r3$.ɵtemplateRefExtractor(TemplateRef, ElementRef));
$r3$.ɵtext(2); $r3$.ɵtext(2);
} }
if (rf & 2) { if (rf & 2) {

View File

@ -6,12 +6,13 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core'; import {Component, Directive, Input, OnDestroy, Pipe, PipeTransform, TemplateRef, ViewContainerRef} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export'; import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition'; import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {containerEl, renderComponent, toHtml} from '../render_util'; import {containerEl, renderComponent, toHtml} from '../render_util';
/// See: `normative.md` /// See: `normative.md`
describe('pipes', () => { describe('pipes', () => {
type $any$ = any; type $any$ = any;
@ -145,7 +146,9 @@ describe('pipes', () => {
static ngDirectiveDef = $r3$.ɵdefineDirective({ static ngDirectiveDef = $r3$.ɵdefineDirective({
type: OneTimeIf, type: OneTimeIf,
selectors: [['', 'oneTimeIf', '']], selectors: [['', 'oneTimeIf', '']],
factory: () => new OneTimeIf($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef()), factory: () => new OneTimeIf(
$r3$.ɵdirectiveInject(ViewContainerRef as any),
$r3$.ɵdirectiveInject(TemplateRef as any)),
inputs: {oneTimeIf: 'oneTimeIf'} inputs: {oneTimeIf: 'oneTimeIf'}
}); });
// /NORMATIVE // /NORMATIVE

View File

@ -6,12 +6,13 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core'; import {Component, Directive, Input, SimpleChanges, TemplateRef, ViewContainerRef, inject} from '../../../src/core';
import * as $r3$ from '../../../src/core_render3_private_export'; import * as $r3$ from '../../../src/core_render3_private_export';
import {ComponentDefInternal} from '../../../src/render3/interfaces/definition'; import {ComponentDefInternal} from '../../../src/render3/interfaces/definition';
import {renderComponent, toHtml} from '../render_util'; import {renderComponent, toHtml} from '../render_util';
/// See: `normative.md` /// See: `normative.md`
describe('template variables', () => { describe('template variables', () => {
type $any$ = any; type $any$ = any;
@ -69,7 +70,9 @@ describe('template variables', () => {
type: ForOfDirective, type: ForOfDirective,
selectors: [['', 'forOf', '']], selectors: [['', 'forOf', '']],
factory: function ForOfDirective_Factory() { factory: function ForOfDirective_Factory() {
return new ForOfDirective($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef()); return new ForOfDirective(
$r3$.ɵdirectiveInject(ViewContainerRef as any),
$r3$.ɵdirectiveInject(TemplateRef as any));
}, },
// TODO(chuckj): Enable when ngForOf enabling lands. // TODO(chuckj): Enable when ngForOf enabling lands.
// features: [NgOnChangesFeature], // features: [NgOnChangesFeature],

View File

@ -8,9 +8,6 @@
import {SelectorFlags} from '@angular/core/src/render3/interfaces/projection'; import {SelectorFlags} from '@angular/core/src/render3/interfaces/projection';
import {Input, TemplateRef, ViewContainerRef, ViewRef} from '../../src/core';
import {defineDirective} from '../../src/render3/definition';
import {injectTemplateRef, injectViewContainerRef} from '../../src/render3/di';
import {AttributeMarker, detectChanges} from '../../src/render3/index'; import {AttributeMarker, detectChanges} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, projection, projectionDef, template, text} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, projection, projectionDef, template, text} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition'; import {RenderFlags} from '../../src/render3/interfaces/definition';

View File

@ -11,7 +11,8 @@ import {RenderFlags} from '@angular/core/src/render3/interfaces/definition';
import {defineComponent} from '../../src/render3/definition'; import {defineComponent} from '../../src/render3/definition';
import {bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di'; import {bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector, injectAttribute} from '../../src/render3/di';
import {PublicFeature, defineDirective, directiveInject, injectChangeDetectorRef, injectElementRef, injectRenderer2, injectTemplateRef, injectViewContainerRef, load} from '../../src/render3/index'; import {PublicFeature, defineDirective, directiveInject, injectRenderer2, load} 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, loadDirective, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, createNodeAtIndex, createLViewData, createTView, element, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, enterView, interpolation2, leaveView, projection, projectionDef, reference, template, text, textBinding, loadDirective, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
import {LInjector} from '../../src/render3/interfaces/injector'; import {LInjector} from '../../src/render3/interfaces/injector';
import {isProceduralRenderer} from '../../src/render3/interfaces/renderer'; import {isProceduralRenderer} from '../../src/render3/interfaces/renderer';
@ -786,445 +787,456 @@ describe('di', () => {
}); });
describe('ElementRef', () => { describe('Special tokens', () => {
it('should create directive with ElementRef dependencies', () => {
let dir !: Directive; describe('ElementRef', () => {
let dirSameInstance !: DirectiveSameInstance;
let divNode !: LElementNode; it('should create directive with ElementRef dependencies', () => {
let dir !: Directive;
let dirSameInstance !: DirectiveSameInstance;
let divNode !: LElementNode;
class Directive {
value: string;
constructor(public elementRef: ElementRef) {
this.value = (elementRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(directiveInject(ElementRef)),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(public elementRef: ElementRef, directive: Directive) {
this.isSameInstance = elementRef === directive.elementRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => dirSameInstance = new DirectiveSameInstance(
directiveInject(ElementRef), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
/** <div dir dirSame></div> */
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', '']);
elementEnd();
divNode = load(0);
}
}, 1, 0, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App);
expect(dir.value).toContain('ElementRef');
expect(dir.elementRef.nativeElement).toEqual(divNode.native);
expect(dirSameInstance.elementRef.nativeElement).toEqual(divNode.native);
// Each ElementRef instance should be unique
expect(dirSameInstance.isSameInstance).toBe(false);
});
it('should create ElementRef with comment if requesting directive is on <ng-template> node',
() => {
let dir !: Directive;
let commentNode !: LContainerNode;
class Directive {
value: string;
constructor(public elementRef: ElementRef) {
this.value = (elementRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(directiveInject(ElementRef)),
features: [PublicFeature],
exportAs: 'dir'
});
}
/** <ng-template dir></ng-template> */
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
template(0, () => {}, 0, 0, null, ['dir', '']);
commentNode = load(0);
}
}, 1, 0, [Directive]);
const fixture = new ComponentFixture(App);
expect(dir.value).toContain('ElementRef');
expect(dir.elementRef.nativeElement).toEqual(commentNode.native);
});
});
describe('TemplateRef', () => {
it('should create directive with TemplateRef dependencies', () => {
class Directive {
value: string;
constructor(public templateRef: TemplateRef<any>) {
this.value = (templateRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => new Directive(directiveInject(TemplateRef as any)),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(templateRef: TemplateRef<any>, directive: Directive) {
this.isSameInstance = templateRef === directive.templateRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => new DirectiveSameInstance(
directiveInject(TemplateRef as any), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
/**
* <ng-template dir dirSame #dir="dir" #dirSame="dirSame">
* {{ dir.value }} - {{ dirSame.value }}
* </ng-template>
*/
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
template(0, function() {
}, 0, 0, undefined, ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
text(3);
}
if (rf & RenderFlags.Update) {
const tmp1 = reference(1) as any;
const tmp2 = reference(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, ''));
}
}, 4, 2, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App);
// Each TemplateRef instance should be unique
expect(fixture.html).toContain('TemplateRef');
expect(fixture.html).toContain('false');
});
});
describe('ViewContainerRef', () => {
it('should create directive with ViewContainerRef dependencies', () => {
class Directive {
value: string;
constructor(public viewContainerRef: ViewContainerRef) {
this.value = (viewContainerRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => new Directive(directiveInject(ViewContainerRef as any)),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(viewContainerRef: ViewContainerRef, directive: Directive) {
this.isSameInstance = viewContainerRef === directive.viewContainerRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => new DirectiveSameInstance(
directiveInject(ViewContainerRef as any), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
/**
* <div dir dirSame #dir="dir" #dirSame="dirSame">
* {{ dir.value }} - {{ dirSame.value }}
* </div>
*/
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(
0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
{ text(3); }
elementEnd();
}
if (rf & RenderFlags.Update) {
const tmp1 = reference(1) as any;
const tmp2 = reference(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, ''));
}
}, 4, 2, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App);
// Each ViewContainerRef instance should be unique
expect(fixture.html).toContain('ViewContainerRef');
expect(fixture.html).toContain('false');
});
});
describe('ChangeDetectorRef', () => {
let dir: Directive;
let dirSameInstance: DirectiveSameInstance;
let comp: MyComp;
class MyComp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyComp,
selectors: [['my-comp']],
factory: () => comp = new MyComp(directiveInject(ChangeDetectorRef as any)),
consts: 1,
vars: 0,
template: function(rf: RenderFlags, ctx: MyComp) {
if (rf & RenderFlags.Create) {
projectionDef();
projection(0);
}
}
});
}
class Directive { class Directive {
value: string; value: string;
constructor(public elementRef: ElementRef) {
this.value = (elementRef.constructor as any).name; constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; }
}
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
type: Directive, type: Directive,
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
factory: () => dir = new Directive(injectElementRef()), factory: () => dir = new Directive(directiveInject(ChangeDetectorRef as any)),
features: [PublicFeature], features: [PublicFeature],
exportAs: 'dir' exportAs: 'dir'
}); });
} }
class DirectiveSameInstance { class DirectiveSameInstance {
isSameInstance: boolean; constructor(public cdr: ChangeDetectorRef) {}
constructor(public elementRef: ElementRef, directive: Directive) {
this.isSameInstance = elementRef === directive.elementRef;
}
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance, type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']], selectors: [['', 'dirSame', '']],
factory: () => dirSameInstance = factory: () => dirSameInstance =
new DirectiveSameInstance(injectElementRef(), directiveInject(Directive)), new DirectiveSameInstance(directiveInject(ChangeDetectorRef as any))
exportAs: 'dirSame'
}); });
} }
/** <div dir dirSame></div> */ const directives = [MyComp, Directive, DirectiveSameInstance, NgIf];
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', '']);
elementEnd();
divNode = load(0);
}
}, 1, 0, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App); it('should inject current component ChangeDetectorRef into directives on the same node as components',
expect(dir.value).toEqual('ElementRef'); () => {
expect(dir.elementRef.nativeElement).toEqual(divNode.native); /** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */
expect(dirSameInstance.elementRef.nativeElement).toEqual(divNode.native); const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
element(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
text(2);
}
if (rf & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
}, 3, 1, directives);
// Each ElementRef instance should be unique const app = renderComponent(MyApp);
expect(dirSameInstance.isSameInstance).toBe(false); // ChangeDetectorRef is the token, ViewRef has historically been the constructor
}); expect(toHtml(app)).toEqual('<my-comp dir="" dirsame=""></my-comp>ViewRef');
expect((comp !.cdr as ViewRef<MyComp>).context).toBe(comp);
it('should create ElementRef with comment if requesting directive is on <ng-template> node', // Each ChangeDetectorRef instance should be unique
() => { expect(dir !.cdr).not.toBe(comp !.cdr);
let dir !: Directive; expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
let commentNode !: LContainerNode; });
class Directive { it('should inject host component ChangeDetectorRef into directives on normal elements',
value: string; () => {
constructor(public elementRef: ElementRef) {
this.value = (elementRef.constructor as any).name; class MyApp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
consts: 3,
vars: 1,
factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
/** <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
if (rf & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
},
directives: directives
});
} }
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(injectElementRef()),
features: [PublicFeature],
exportAs: 'dir'
});
}
/** <ng-template dir></ng-template> */ const app = renderComponent(MyApp);
const App = createComponent('app', function(rf: RenderFlags, ctx: any) { expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
if (rf & RenderFlags.Create) { expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
template(0, () => {}, 0, 0, null, ['dir', '']);
commentNode = load(0); // Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives in a component\'s ContentChildren',
() => {
class MyApp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
consts: 4,
vars: 1,
factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
/**
* <my-comp>
* <div dir dirSameInstance #dir="dir"></div>
* </my-comp>
* {{ dir.value }}
*/
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
{ element(1, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); }
elementEnd();
text(3);
}
if (rf & RenderFlags.Update) {
const tmp = reference(2) as any;
textBinding(3, bind(tmp.value));
}
},
directives: directives
});
} }
}, 1, 0, [Directive]);
const fixture = new ComponentFixture(App); const app = renderComponent(MyApp);
expect(dir.value).toEqual('ElementRef'); expect(toHtml(app)).toEqual('<my-comp><div dir="" dirsame=""></div></my-comp>ViewRef');
expect(dir.elementRef.nativeElement).toEqual(commentNode.native); expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
});
});
describe('TemplateRef', () => { // Each ChangeDetectorRef instance should be unique
it('should create directive with TemplateRef dependencies', () => { expect(dir !.cdr).not.toBe(app !.cdr);
class Directive { expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
value: string; });
constructor(public templateRef: TemplateRef<any>) {
this.value = (templateRef.constructor as any).name;
}
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => new Directive(injectTemplateRef()),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance { it('should inject host component ChangeDetectorRef into directives in embedded views', () => {
isSameInstance: boolean;
constructor(templateRef: TemplateRef<any>, directive: Directive) {
this.isSameInstance = templateRef === directive.templateRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => new DirectiveSameInstance(injectTemplateRef(), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
/** class MyApp {
* <ng-template dir dirSame #dir="dir" #dirSame="dirSame"> showing = true;
* {{ dir.value }} - {{ dirSame.value }}
* </ng-template>
*/
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
template(0, function() {
}, 0, 0, undefined, ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
text(3);
}
if (rf & RenderFlags.Update) {
const tmp1 = reference(1) as any;
const tmp2 = reference(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, ''));
}
}, 4, 2, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App); constructor(public cdr: ChangeDetectorRef) {}
// Each TemplateRef instance should be unique
expect(fixture.html).toEqual('TemplateRef-false');
});
});
describe('ViewContainerRef', () => { static ngComponentDef = defineComponent({
it('should create directive with ViewContainerRef dependencies', () => { type: MyApp,
class Directive { selectors: [['my-app']],
value: string; factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
constructor(public viewContainerRef: ViewContainerRef) { consts: 1,
this.value = (viewContainerRef.constructor as any).name; vars: 0,
} /**
static ngDirectiveDef = defineDirective({ * % if (showing) {
type: Directive,
selectors: [['', 'dir', '']],
factory: () => new Directive(injectViewContainerRef()),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
isSameInstance: boolean;
constructor(viewContainerRef: ViewContainerRef, directive: Directive) {
this.isSameInstance = viewContainerRef === directive.viewContainerRef;
}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory:
() => new DirectiveSameInstance(injectViewContainerRef(), directiveInject(Directive)),
exportAs: 'dirSame'
});
}
/**
* <div dir dirSame #dir="dir" #dirSame="dirSame">
* {{ dir.value }} - {{ dirSame.value }}
* </div>
*/
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']);
{ text(3); }
elementEnd();
}
if (rf & RenderFlags.Update) {
const tmp1 = reference(1) as any;
const tmp2 = reference(2) as any;
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, ''));
}
}, 4, 2, [Directive, DirectiveSameInstance]);
const fixture = new ComponentFixture(App);
// Each ViewContainerRef instance should be unique
expect(fixture.html).toEqual('<div dir="" dirsame="">ViewContainerRef-false</div>');
});
});
describe('ChangeDetectorRef', () => {
let dir: Directive;
let dirSameInstance: DirectiveSameInstance;
let comp: MyComp;
class MyComp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyComp,
selectors: [['my-comp']],
factory: () => comp = new MyComp(injectChangeDetectorRef()),
consts: 1,
vars: 0,
template: function(rf: RenderFlags, ctx: MyComp) {
if (rf & RenderFlags.Create) {
projectionDef();
projection(0);
}
}
});
}
class Directive {
value: string;
constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; }
static ngDirectiveDef = defineDirective({
type: Directive,
selectors: [['', 'dir', '']],
factory: () => dir = new Directive(injectChangeDetectorRef()),
features: [PublicFeature],
exportAs: 'dir'
});
}
class DirectiveSameInstance {
constructor(public cdr: ChangeDetectorRef) {}
static ngDirectiveDef = defineDirective({
type: DirectiveSameInstance,
selectors: [['', 'dirSame', '']],
factory: () => dirSameInstance = new DirectiveSameInstance(injectChangeDetectorRef())
});
}
const directives = [MyComp, Directive, DirectiveSameInstance, NgIf];
it('should inject current component ChangeDetectorRef into directives on the same node as components',
() => {
/** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */
const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
element(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
text(2);
}
if (rf & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
}, 3, 1, directives);
const app = renderComponent(MyApp);
// ChangeDetectorRef is the token, ViewRef has historically been the constructor
expect(toHtml(app)).toEqual('<my-comp dir="" dirsame=""></my-comp>ViewRef');
expect((comp !.cdr as ViewRef<MyComp>).context).toBe(comp);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(comp !.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives on normal elements', () => {
class MyApp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
consts: 3,
vars: 1,
factory: () => new MyApp(injectChangeDetectorRef()),
/** <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
if (rf & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
},
directives: directives
});
}
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives in a component\'s ContentChildren',
() => {
class MyApp {
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
consts: 4,
vars: 1,
factory: () => new MyApp(injectChangeDetectorRef()),
/**
* <my-comp>
* <div dir dirSameInstance #dir="dir"></div>
* </my-comp>
* {{ dir.value }}
*/
template: function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementStart(0, 'my-comp');
{ element(1, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); }
elementEnd();
text(3);
}
if (rf & RenderFlags.Update) {
const tmp = reference(2) as any;
textBinding(3, bind(tmp.value));
}
},
directives: directives
});
}
const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<my-comp><div dir="" dirsame=""></div></my-comp>ViewRef');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app !.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives in embedded views', () => {
class MyApp {
showing = true;
constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({
type: MyApp,
selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()),
consts: 1,
vars: 0,
/**
* % if (showing) {
* <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div> * <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div>
* % } * % }
*/ */
template: function(rf: RenderFlags, ctx: MyApp) { template: function(rf: RenderFlags, ctx: MyApp) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
container(0); container(0);
}
if (rf & RenderFlags.Update) {
containerRefreshStart(0);
{
if (ctx.showing) {
let rf1 = embeddedViewStart(0, 3, 1);
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
}
embeddedViewEnd();
} }
containerRefreshEnd(); if (rf & RenderFlags.Update) {
} containerRefreshStart(0);
}, {
directives: directives if (ctx.showing) {
}); let rf1 = embeddedViewStart(0, 3, 1);
} if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
const app = renderComponent(MyApp); { text(2); }
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>'); elementEnd();
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app); }
if (rf1 & RenderFlags.Update) {
// Each ChangeDetectorRef instance should be unique const tmp = reference(1) as any;
expect(dir !.cdr).not.toBe(app.cdr); textBinding(2, bind(tmp.value));
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr); }
}); }
embeddedViewEnd();
it('should inject host component ChangeDetectorRef into directives on containers', () => { }
function C1(rf1: RenderFlags, ctx1: any) { containerRefreshEnd();
if (rf1 & RenderFlags.Create) { }
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); },
{ text(2); } directives: directives
elementEnd(); });
} }
if (rf1 & RenderFlags.Update) {
const tmp = reference(1) as any; const app = renderComponent(MyApp);
textBinding(2, bind(tmp.value)); expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
it('should inject host component ChangeDetectorRef into directives on containers', () => {
function C1(rf1: RenderFlags, ctx1: any) {
if (rf1 & RenderFlags.Create) {
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
{ text(2); }
elementEnd();
}
if (rf1 & RenderFlags.Update) {
const tmp = reference(1) as any;
textBinding(2, bind(tmp.value));
}
} }
}
class MyApp { class MyApp {
showing = true; showing = true;
constructor(public cdr: ChangeDetectorRef) {} constructor(public cdr: ChangeDetectorRef) {}
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: () => new MyApp(injectChangeDetectorRef()), factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 0, vars: 0,
/** <div *ngIf="showing" dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */ /** <div *ngIf="showing" dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
template: function(rf: RenderFlags, ctx: MyApp) { template: function(rf: RenderFlags, ctx: MyApp) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template(0, C1, 3, 1, null, ['ngIf', 'showing']); template(0, C1, 3, 1, null, ['ngIf', 'showing']);
} }
}, },
directives: directives directives: directives
}); });
} }
const app = renderComponent(MyApp); const app = renderComponent(MyApp);
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>'); expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app); expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
// Each ChangeDetectorRef instance should be unique // Each ChangeDetectorRef instance should be unique
expect(dir !.cdr).not.toBe(app.cdr); expect(dir !.cdr).not.toBe(app.cdr);
expect(dir !.cdr).not.toBe(dirSameInstance !.cdr); expect(dir !.cdr).not.toBe(dirSameInstance !.cdr);
});
}); });
}); });

View File

@ -10,8 +10,7 @@ import {ElementRef, TemplateRef, ViewContainerRef} from '@angular/core';
import {RenderFlags} from '@angular/core/src/render3'; import {RenderFlags} from '@angular/core/src/render3';
import {RendererStyleFlags2, RendererType2} from '../../src/render/api'; import {RendererStyleFlags2, RendererType2} from '../../src/render/api';
import {createTemplateRef, getOrCreateNodeInjectorForNode} from '../../src/render3/di'; import {AttributeMarker, defineComponent, defineDirective} from '../../src/render3/index';
import {AttributeMarker, defineComponent, defineDirective, injectElementRef, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {NO_CHANGE, 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, listener, load, loadDirective, projection, projectionDef, text, textBinding, template} from '../../src/render3/instructions'; import {NO_CHANGE, 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, listener, load, loadDirective, projection, projectionDef, text, textBinding, template} from '../../src/render3/instructions';
import {InitialStylingFlags} from '../../src/render3/interfaces/definition'; import {InitialStylingFlags} from '../../src/render3/interfaces/definition';
@ -21,9 +20,10 @@ import {sanitizeUrl} from '../../src/sanitization/sanitization';
import {Sanitizer, SecurityContext} from '../../src/sanitization/security'; import {Sanitizer, SecurityContext} from '../../src/sanitization/security';
import {NgIf} from './common_with_def'; import {NgIf} from './common_with_def';
import {ComponentFixture, TemplateFixture, containerEl, createComponent, renderToHtml} from './render_util'; import {ComponentFixture, TemplateFixture, createComponent, renderToHtml} from './render_util';
import {MONKEY_PATCH_KEY_NAME, getContext} from '../../src/render3/context_discovery'; import {MONKEY_PATCH_KEY_NAME, getContext} from '../../src/render3/context_discovery';
import {StylingIndex} from '../../src/render3/styling'; import {StylingIndex} from '../../src/render3/styling';
import {directiveInject} from '../../src/render3/di';
describe('render3 integration test', () => { describe('render3 integration test', () => {
@ -649,7 +649,9 @@ describe('render3 integration test', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
type: TestDirective, type: TestDirective,
selectors: [['', 'testDirective', '']], selectors: [['', 'testDirective', '']],
factory: () => new TestDirective(injectTemplateRef(), injectViewContainerRef()), factory:
() => new TestDirective(
directiveInject(TemplateRef as any), directiveInject(ViewContainerRef as any)),
}); });
} }
@ -754,7 +756,9 @@ describe('render3 integration test', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
type: TestDirective, type: TestDirective,
selectors: [['', 'testDirective', '']], selectors: [['', 'testDirective', '']],
factory: () => new TestDirective(injectTemplateRef(), injectViewContainerRef()), factory:
() => new TestDirective(
directiveInject(TemplateRef as any), directiveInject(ViewContainerRef as any)),
}); });
} }
@ -822,7 +826,7 @@ describe('render3 integration test', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
type: Directive, type: Directive,
selectors: [['', 'dir', '']], selectors: [['', 'dir', '']],
factory: () => new Directive(injectElementRef()), factory: () => new Directive(directiveInject(ElementRef)),
}); });
} }

View File

@ -11,7 +11,7 @@ import 'reflect-metadata';
import {InjectorDef, defineInjectable} from '@angular/core/src/di/defs'; import {InjectorDef, defineInjectable} from '@angular/core/src/di/defs';
import {Injectable} from '@angular/core/src/di/injectable'; import {Injectable} from '@angular/core/src/di/injectable';
import {inject, setCurrentInjector} from '@angular/core/src/di/injector'; import {inject, setCurrentInjector} from '@angular/core/src/di/injector';
import {ivyEnabled} from '@angular/core/src/ivy_switch'; import {ivyEnabled} from '@angular/core/src/ivy_switch/compiler/index';
import {Component, HostBinding, HostListener, Input, Output, Pipe} from '@angular/core/src/metadata/directives'; import {Component, HostBinding, HostListener, Input, Output, Pipe} from '@angular/core/src/metadata/directives';
import {NgModule, NgModuleDefInternal} from '@angular/core/src/metadata/ng_module'; import {NgModule, NgModuleDefInternal} from '@angular/core/src/metadata/ng_module';
import {ComponentDefInternal, PipeDefInternal} from '@angular/core/src/render3/interfaces/definition'; import {ComponentDefInternal, PipeDefInternal} from '@angular/core/src/render3/interfaces/definition';

View File

@ -10,11 +10,14 @@ 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 {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, templateRefExtractor} from '../../src/render3/di'; import {directiveInject} from '../../src/render3/di';
import {AttributeMarker, QueryList, defineComponent, defineDirective, detectChanges, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
import {AttributeMarker, QueryList, defineComponent, defineDirective, detectChanges} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective, loadElement, loadQueryList, reference, registerContentQuery, template} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective, loadElement, 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, QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF} from '../../src/render3/query';
import {templateRefExtractor} from '../../src/render3/view_engine_compatibility';
import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def'; import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def';
import {ComponentFixture, TemplateFixture, createComponent, createDirective, renderComponent} from './render_util'; import {ComponentFixture, TemplateFixture, createComponent, createDirective, renderComponent} from './render_util';
@ -118,7 +121,7 @@ describe('query', () => {
2, 0, [Child], [], 2, 0, [Child], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, Child, false, QUERY_READ_ELEMENT_REF); query(0, Child, false, QUERY_READ_ELEMENT_REF(ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -226,7 +229,7 @@ describe('query', () => {
4, 0, [], [], 4, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_FROM_NODE); query(0, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -263,8 +266,8 @@ describe('query', () => {
6, 0, [], [], 6, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_FROM_NODE); query(0, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
query(1, ['bar'], false, QUERY_READ_FROM_NODE); query(1, ['bar'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -312,7 +315,7 @@ describe('query', () => {
6, 0, [], [], 6, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE); query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -349,7 +352,7 @@ describe('query', () => {
4, 0, [], [], 4, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF); query(0, ['foo'], false, QUERY_READ_ELEMENT_REF(ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -385,7 +388,7 @@ describe('query', () => {
3, 0, [], [], 3, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF); query(0, ['foo'], false, QUERY_READ_ELEMENT_REF(ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -421,7 +424,7 @@ describe('query', () => {
3, 0, [], [], 3, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -485,8 +488,8 @@ describe('query', () => {
5, 0, [], [], 5, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_ELEMENT_REF); query(0, ['foo'], true, QUERY_READ_ELEMENT_REF(ElementRef));
query(1, ['foo'], false, QUERY_READ_ELEMENT_REF); query(1, ['foo'], false, QUERY_READ_ELEMENT_REF(ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -520,7 +523,7 @@ describe('query', () => {
3, 0, [], [], 3, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF); query(0, ['foo'], false, QUERY_READ_CONTAINER_REF(ViewContainerRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -551,7 +554,7 @@ describe('query', () => {
3, 0, [], [], 3, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF); query(0, ['foo'], false, QUERY_READ_CONTAINER_REF(ViewContainerRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -584,7 +587,7 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF); query(0, ['foo'], false, QUERY_READ_ELEMENT_REF(ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -618,7 +621,7 @@ describe('query', () => {
3, 0, [], [], 3, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], undefined, QUERY_READ_FROM_NODE); query(0, ['foo'], undefined, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -650,7 +653,7 @@ describe('query', () => {
3, 0, [], [], 3, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_TEMPLATE_REF); query(0, ['foo'], false, QUERY_READ_TEMPLATE_REF(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -687,7 +690,7 @@ describe('query', () => {
3, 0, [Child], [], 3, 0, [Child], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -732,7 +735,7 @@ describe('query', () => {
3, 0, [Child], [], 3, 0, [Child], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -770,7 +773,7 @@ describe('query', () => {
3, 0, [Child], [], 3, 0, [Child], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -810,7 +813,7 @@ describe('query', () => {
4, 0, [Child1, Child2], [], 4, 0, [Child1, Child2], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE); query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -849,8 +852,8 @@ describe('query', () => {
5, 0, [Child], [], 5, 0, [Child], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
query(1, ['bar'], true, QUERY_READ_FROM_NODE); query(1, ['bar'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -893,7 +896,7 @@ describe('query', () => {
3, 0, [Child], [], 3, 0, [Child], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], undefined, QUERY_READ_ELEMENT_REF); query(0, ['foo'], undefined, QUERY_READ_ELEMENT_REF(ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -931,7 +934,7 @@ describe('query', () => {
4, 0, [Child], [], 4, 0, [Child], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE); query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -993,7 +996,7 @@ describe('query', () => {
selectors: [['', 'vc', '']], selectors: [['', 'vc', '']],
factory: () => { factory: () => {
const directiveInstance = const directiveInstance =
new ViewContainerManipulatorDirective(injectViewContainerRef()); new ViewContainerManipulatorDirective(directiveInject(ViewContainerRef as any));
directiveInstances.push(directiveInstance); directiveInstances.push(directiveInstance);
return directiveInstance; return directiveInstance;
} }
@ -1039,7 +1042,7 @@ describe('query', () => {
3, 1, [NgIf], [], 3, 1, [NgIf], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -1100,7 +1103,7 @@ describe('query', () => {
viewQuery: function(rf: RenderFlags, ctx: Cmpt) { viewQuery: function(rf: RenderFlags, ctx: Cmpt) {
let tmp: any; let tmp: any;
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
@ -1170,10 +1173,12 @@ describe('query', () => {
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template( template(
1, Cmpt_Template_1, 2, 1, null, null, ['tpl1', ''], templateRefExtractor); 1, Cmpt_Template_1, 2, 1, null, null, ['tpl1', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(3, 'div', ['id', 'middle'], ['foo', '']); element(3, 'div', ['id', 'middle'], ['foo', '']);
template( template(
5, Cmpt_Template_5, 2, 1, null, null, ['tpl2', ''], templateRefExtractor); 5, Cmpt_Template_5, 2, 1, null, null, ['tpl2', ''],
templateRefExtractor(TemplateRef, ElementRef));
template(7, null, 0, 0, null, [AttributeMarker.SelectOnly, 'vc']); template(7, null, 0, 0, null, [AttributeMarker.SelectOnly, 'vc']);
} }
@ -1186,7 +1191,7 @@ describe('query', () => {
9, 0, [ViewContainerManipulatorDirective], [], 9, 0, [ViewContainerManipulatorDirective], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -1268,7 +1273,9 @@ describe('query', () => {
template: function(rf: RenderFlags, ctx: any) { template: function(rf: RenderFlags, ctx: any) {
let tmp: any; let tmp: any;
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template(1, Cmpt_Template_1, 2, 1, null, [], ['tpl', ''], templateRefExtractor); template(
1, Cmpt_Template_1, 2, 1, null, [], ['tpl', ''],
templateRefExtractor(TemplateRef, ElementRef));
template(3, null, 0, 0, null, [AttributeMarker.SelectOnly, 'vc']); template(3, null, 0, 0, null, [AttributeMarker.SelectOnly, 'vc']);
template(4, null, 0, 0, null, [AttributeMarker.SelectOnly, 'vc']); template(4, null, 0, 0, null, [AttributeMarker.SelectOnly, 'vc']);
} }
@ -1281,7 +1288,7 @@ describe('query', () => {
viewQuery: (rf: RenderFlags, cmpt: Cmpt) => { viewQuery: (rf: RenderFlags, cmpt: Cmpt) => {
let tmp: any; let tmp: any;
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && queryRefresh(tmp = load<QueryList<any>>(0)) &&
@ -1341,7 +1348,7 @@ describe('query', () => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template( template(
1, MyApp_Template_1, 2, 0, undefined, undefined, ['tpl', ''], 1, MyApp_Template_1, 2, 0, undefined, undefined, ['tpl', ''],
templateRefExtractor); templateRefExtractor(TemplateRef, ElementRef));
template(3, null, 0, 0, null, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']); template(3, null, 0, 0, null, [AttributeMarker.SelectOnly, 'ngTemplateOutlet']);
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
@ -1353,7 +1360,7 @@ describe('query', () => {
viewQuery: (rf: RenderFlags, myApp: MyApp) => { viewQuery: (rf: RenderFlags, myApp: MyApp) => {
let tmp: any; let tmp: any;
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
queryRefresh(tmp = load<QueryList<any>>(0)) && queryRefresh(tmp = load<QueryList<any>>(0)) &&
@ -1418,7 +1425,7 @@ describe('query', () => {
2, 0, [], [], 2, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -1483,7 +1490,7 @@ describe('query', () => {
6, 0, [], [], 6, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -1560,7 +1567,7 @@ describe('query', () => {
2, 0, [], [], 2, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -1640,7 +1647,7 @@ describe('query', () => {
2, 0, [], [], 2, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -1709,8 +1716,8 @@ describe('query', () => {
5, 0, [], [], 5, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
query(1, ['foo'], false, QUERY_READ_FROM_NODE); query(1, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -1790,7 +1797,7 @@ describe('query', () => {
2, 0, [], [], 2, 0, [], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], false, QUERY_READ_FROM_NODE); query(0, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -1844,7 +1851,8 @@ describe('query', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
type: SomeDir, type: SomeDir,
selectors: [['', 'someDir', '']], selectors: [['', 'someDir', '']],
factory: () => new SomeDir(injectViewContainerRef(), injectTemplateRef()) factory: () => new SomeDir(
directiveInject(ViewContainerRef as any), directiveInject(TemplateRef as any))
}); });
} }
@ -1870,7 +1878,7 @@ describe('query', () => {
4, 0, [SomeDir], [], 4, 0, [SomeDir], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE); query(0, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -1907,8 +1915,10 @@ describe('query', () => {
type: WithContentDirective, type: WithContentDirective,
selectors: [['', 'with-content', '']], selectors: [['', 'with-content', '']],
factory: () => new WithContentDirective(), factory: () => new WithContentDirective(),
contentQueries: contentQueries: () => {
() => { registerContentQuery(query(null, ['foo'], true, QUERY_READ_FROM_NODE)); }, registerContentQuery(
query(null, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
},
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
withContentInstance = loadDirective<WithContentDirective>(dirIndex); withContentInstance = loadDirective<WithContentDirective>(dirIndex);
@ -1929,8 +1939,10 @@ describe('query', () => {
template: function(rf: RenderFlags, ctx: any) {}, template: function(rf: RenderFlags, ctx: any) {},
consts: 0, consts: 0,
vars: 0, vars: 0,
contentQueries: contentQueries: () => {
() => { registerContentQuery(query(null, ['foo'], false, QUERY_READ_FROM_NODE)); }, registerContentQuery(
query(null, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
},
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
shallowCompInstance = loadDirective<ShallowComp>(dirIndex); shallowCompInstance = loadDirective<ShallowComp>(dirIndex);
@ -2046,7 +2058,7 @@ describe('query', () => {
6, 0, [WithContentDirective], [], 6, 0, [WithContentDirective], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE); query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -2086,7 +2098,7 @@ describe('query', () => {
6, 0, [WithContentDirective], [], 6, 0, [WithContentDirective], [],
function(rf: RenderFlags, ctx: any) { function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
query(0, ['bar'], true, QUERY_READ_FROM_NODE); query(0, ['bar'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef));
} }
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
let tmp: any; let tmp: any;
@ -2110,7 +2122,8 @@ describe('query', () => {
contentQueries: () => { contentQueries: () => {
// @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, QUERY_READ_FROM_NODE)); registerContentQuery(query(
null, ['foo', 'bar', 'baz'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
}, },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
@ -2174,7 +2187,8 @@ describe('query', () => {
contentQueries: () => { contentQueries: () => {
// @ContentChildren('foo, bar, baz', {descendants: true}) fooBars: // @ContentChildren('foo, bar, baz', {descendants: true}) fooBars:
// QueryList<ElementRef>; // QueryList<ElementRef>;
registerContentQuery(query(null, ['foo'], false, QUERY_READ_FROM_NODE)); registerContentQuery(
query(null, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
}, },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
@ -2227,7 +2241,8 @@ describe('query', () => {
factory: () => new ShallowQueryDirective(), factory: () => new ShallowQueryDirective(),
contentQueries: () => { contentQueries: () => {
// @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>; // @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>;
registerContentQuery(query(null, ['foo'], false, QUERY_READ_FROM_NODE)); registerContentQuery(
query(null, ['foo'], false, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
}, },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;
@ -2247,7 +2262,8 @@ describe('query', () => {
factory: () => new DeepQueryDirective(), factory: () => new DeepQueryDirective(),
contentQueries: () => { contentQueries: () => {
// @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>; // @ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>;
registerContentQuery(query(null, ['foo'], true, QUERY_READ_FROM_NODE)); registerContentQuery(
query(null, ['foo'], true, QUERY_READ_FROM_NODE(TemplateRef, ElementRef)));
}, },
contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => { contentQueriesRefresh: (dirIndex: number, queryStartIdx: number) => {
let tmp: any; let tmp: any;

View File

@ -6,13 +6,19 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {ChangeDetectorRef} from '@angular/core/src/change_detection/change_detector_ref';
import {ElementRef} from '@angular/core/src/linker/element_ref';
import {TemplateRef} from '@angular/core/src/linker/template_ref';
import {ViewContainerRef} from '@angular/core/src/linker/view_container_ref';
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util'; import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
import {Injector} from '../../src/di/injector'; import {Injector} from '../../src/di/injector';
import {R3_CHANGE_DETECTOR_REF_FACTORY, R3_ELEMENT_REF_FACTORY, R3_TEMPLATE_REF_FACTORY, R3_VIEW_CONTAINER_REF_FACTORY} from '../../src/ivy_switch/runtime/ivy_switch_on';
import {PlayerHandler} from '../../src/render3/animations/interfaces'; import {PlayerHandler} from '../../src/render3/animations/interfaces';
import {CreateComponentOptions} from '../../src/render3/component'; import {CreateComponentOptions} from '../../src/render3/component';
import {getContext, isComponentInstance} from '../../src/render3/context_discovery'; import {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 {ComponentTemplate, ComponentType, DirectiveDefInternal, DirectiveType, PublicFeature, RenderFlags, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index'; import {ComponentTemplate, ComponentType, DirectiveDefInternal, DirectiveType, PublicFeature, RenderFlags, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
import {renderTemplate} from '../../src/render3/instructions'; import {renderTemplate} from '../../src/render3/instructions';
import {DirectiveDefList, DirectiveTypesOrFactory, PipeDefInternal, PipeDefList, PipeTypesOrFactory} from '../../src/render3/interfaces/definition'; import {DirectiveDefList, DirectiveTypesOrFactory, PipeDefInternal, PipeDefList, PipeTypesOrFactory} from '../../src/render3/interfaces/definition';
@ -208,6 +214,10 @@ function toDefs(
beforeEach(resetDOM); beforeEach(resetDOM);
// This is necessary so we can switch between the Render2 version and the Ivy version
// of special objects like ElementRef and TemplateRef.
beforeEach(enableIvyInjectableFactories);
/** /**
* @deprecated use `TemplateFixture` or `ComponentFixture` * @deprecated use `TemplateFixture` or `ComponentFixture`
*/ */
@ -285,3 +295,17 @@ export function createDirective(
export const renderer: Renderer3 = null as any as Document; export const renderer: Renderer3 = null as any as Document;
export const element: RElement = null as any as HTMLElement; export const element: RElement = null as any as HTMLElement;
export const text: RText = null as any as Text; export const text: RText = null as any as Text;
/**
* Switches between Render2 version of special objects like ElementRef and the Ivy version
* of these objects. It's necessary to keep them separate so that we don't pull in fns
* like injectElementRef() prematurely.
*/
export function enableIvyInjectableFactories() {
(ElementRef as any)[NG_ELEMENT_ID] = () => R3_ELEMENT_REF_FACTORY(ElementRef);
(TemplateRef as any)[NG_ELEMENT_ID] = () => R3_TEMPLATE_REF_FACTORY(TemplateRef, ElementRef);
(ViewContainerRef as any)[NG_ELEMENT_ID] = () =>
R3_VIEW_CONTAINER_REF_FACTORY(ViewContainerRef, ElementRef);
(ChangeDetectorRef as any)[NG_ELEMENT_ID] = () => R3_CHANGE_DETECTOR_REF_FACTORY();
}

View File

@ -8,11 +8,12 @@
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 {templateRefExtractor} from '../../src/render3/di'; import {directiveInject} from '../../src/render3/di';
import {AttributeMarker, NgOnChangesFeature, defineComponent, defineDirective, definePipe, injectComponentFactoryResolver, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index'; import {AttributeMarker, NgOnChangesFeature, defineComponent, defineDirective, definePipe, injectComponentFactoryResolver} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation3, loadDirective, nextContext, projection, projectionDef, reference, template, text, textBinding} from '../../src/render3/instructions'; import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation3, loadDirective, 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';
import {NgModuleFactory} from '../../src/render3/ng_module_ref'; import {NgModuleFactory} from '../../src/render3/ng_module_ref';
import {pipe, pipeBind1} from '../../src/render3/pipe'; import {pipe, pipeBind1} from '../../src/render3/pipe';
import {NgForOf} from '../../test/render3/common_with_def'; import {NgForOf} from '../../test/render3/common_with_def';
@ -23,7 +24,7 @@ import {ComponentFixture, TemplateFixture, createComponent} from './render_util'
describe('ViewContainerRef', () => { describe('ViewContainerRef', () => {
let directiveInstance: DirectiveWithVCRef|null; let directiveInstance: DirectiveWithVCRef|null;
beforeEach(() => { directiveInstance = null; }); beforeEach(() => directiveInstance = null);
class DirectiveWithVCRef { class DirectiveWithVCRef {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
@ -31,7 +32,7 @@ describe('ViewContainerRef', () => {
selectors: [['', 'vcref', '']], selectors: [['', 'vcref', '']],
factory: () => directiveInstance = new DirectiveWithVCRef( factory: () => directiveInstance = new DirectiveWithVCRef(
injectViewContainerRef(), injectComponentFactoryResolver()), directiveInject(ViewContainerRef as any), injectComponentFactoryResolver()),
inputs: {tplRef: 'tplRef'} inputs: {tplRef: 'tplRef'}
}); });
@ -66,7 +67,9 @@ describe('ViewContainerRef', () => {
* <p vcref [tplRef]="tplRef"></p> * <p vcref [tplRef]="tplRef"></p>
*/ */
function createTemplate() { function createTemplate() {
template(0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''], templateRefExtractor); template(
0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'p', ['vcref', '']); element(2, 'p', ['vcref', '']);
} }
@ -83,7 +86,9 @@ describe('ViewContainerRef', () => {
* <footer></footer> * <footer></footer>
*/ */
function createTemplate() { function createTemplate() {
template(0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''], templateRefExtractor); template(
0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'header', ['vcref', '']); element(2, 'header', ['vcref', '']);
element(3, 'footer'); element(3, 'footer');
} }
@ -119,7 +124,9 @@ describe('ViewContainerRef', () => {
* <footer></footer> * <footer></footer>
*/ */
function createTemplate() { function createTemplate() {
template(0, embeddedTemplate, 1, 1, null, [], ['tplRef', ''], templateRefExtractor); template(
0, embeddedTemplate, 1, 1, null, [], ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'header-cmp', ['vcref', '']); element(2, 'header-cmp', ['vcref', '']);
element(3, 'footer'); element(3, 'footer');
} }
@ -155,7 +162,9 @@ describe('ViewContainerRef', () => {
* <div vcref [tplRef]="tplRef"></div> * <div vcref [tplRef]="tplRef"></div>
*/ */
function createTemplate() { function createTemplate() {
template(0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''], templateRefExtractor); template(
0, embeddedTemplate, 1, 1, null, null, ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'div', ['vcref', '']); element(2, 'div', ['vcref', '']);
element(3, 'div', ['vcref', '']); element(3, 'div', ['vcref', '']);
@ -186,7 +195,8 @@ describe('ViewContainerRef', () => {
*/ */
function createTemplate() { function createTemplate() {
template( template(
0, embeddedTemplate, 1, 1, null, ['vcref', ''], ['tplRef', ''], templateRefExtractor); 0, embeddedTemplate, 1, 1, null, ['vcref', ''], ['tplRef', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'footer'); element(2, 'footer');
} }
@ -225,7 +235,8 @@ describe('ViewContainerRef', () => {
type: TestDirective, type: TestDirective,
selectors: [['', 'testdir', '']], selectors: [['', 'testdir', '']],
factory: () => { factory: () => {
const instance = new TestDirective(injectViewContainerRef(), injectTemplateRef()); const instance = new TestDirective(
directiveInject(ViewContainerRef as any), directiveInject(TemplateRef as any));
directiveInstances.push(instance); directiveInstances.push(instance);
@ -299,8 +310,9 @@ describe('ViewContainerRef', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
type: TestDirective, type: TestDirective,
selectors: [['', 'testdir', '']], selectors: [['', 'testdir', '']],
factory: () => directiveInstance = factory: () => directiveInstance = new TestDirective(
new TestDirective(injectViewContainerRef(), injectTemplateRef()) directiveInject(ViewContainerRef as any),
directiveInject(TemplateRef as any))
}); });
constructor(private _vcRef: ViewContainerRef, private _tplRef: TemplateRef<{}>) {} constructor(private _vcRef: ViewContainerRef, private _tplRef: TemplateRef<{}>) {}
@ -455,7 +467,8 @@ describe('ViewContainerRef', () => {
template: (rf: RenderFlags, cmp: SomeComponent) => { template: (rf: RenderFlags, cmp: SomeComponent) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template( template(
0, SomeComponent_Template_0, 2, 3, null, [], ['foo', ''], templateRefExtractor); 0, SomeComponent_Template_0, 2, 3, null, [], ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
pipe(2, 'starPipe'); pipe(2, 'starPipe');
element(3, 'child', ['vcref', '']); element(3, 'child', ['vcref', '']);
pipe(4, 'starPipe'); pipe(4, 'starPipe');
@ -495,7 +508,7 @@ describe('ViewContainerRef', () => {
static ngDirectiveDef = defineDirective({ static ngDirectiveDef = defineDirective({
type: InsertionDir, type: InsertionDir,
selectors: [['', 'tplDir', '']], selectors: [['', 'tplDir', '']],
factory: () => new InsertionDir(injectViewContainerRef()), factory: () => new InsertionDir(directiveInject(ViewContainerRef as any)),
inputs: {tplDir: 'tplDir'} inputs: {tplDir: 'tplDir'}
}); });
} }
@ -546,7 +559,9 @@ describe('ViewContainerRef', () => {
*/ */
const Parent = createComponent('parent', function(rf: RenderFlags, parent: any) { const Parent = createComponent('parent', function(rf: RenderFlags, parent: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template(0, fooTemplate, 2, 1, null, null, ['foo', ''], templateRefExtractor); template(
0, fooTemplate, 2, 1, null, null, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'child'); element(2, 'child');
} }
@ -637,7 +652,9 @@ describe('ViewContainerRef', () => {
*/ */
const Parent = createComponent('parent', function(rf: RenderFlags, parent: any) { const Parent = createComponent('parent', function(rf: RenderFlags, parent: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template(0, rowTemplate, 3, 2, null, null, ['rowTemplate', ''], templateRefExtractor); template(
0, rowTemplate, 3, 2, null, null, ['rowTemplate', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'loop-comp'); element(2, 'loop-comp');
} }
@ -651,7 +668,9 @@ describe('ViewContainerRef', () => {
function rowTemplate(rf: RenderFlags, ctx: any) { function rowTemplate(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template(0, cellTemplate, 2, 3, null, null, ['cellTemplate', ''], templateRefExtractor); template(
0, cellTemplate, 2, 3, null, null, ['cellTemplate', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'loop-comp'); element(2, 'loop-comp');
} }
@ -1196,7 +1215,9 @@ describe('ViewContainerRef', () => {
vars: 2, vars: 2,
template: (rf: RenderFlags, cmp: Parent) => { template: (rf: RenderFlags, cmp: Parent) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template(0, embeddedTemplate, 2, 1, null, null, ['foo', ''], templateRefExtractor); template(
0, embeddedTemplate, 2, 1, null, null, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementStart(2, 'child'); elementStart(2, 'child');
{ {
elementStart(3, 'header', ['vcref', '']); elementStart(3, 'header', ['vcref', '']);
@ -1291,7 +1312,8 @@ describe('ViewContainerRef', () => {
template: (rf: RenderFlags, cmp: Parent) => { template: (rf: RenderFlags, cmp: Parent) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template( template(
0, embeddedTemplate, 2, 1, null, undefined, ['foo', ''], templateRefExtractor); 0, embeddedTemplate, 2, 1, null, undefined, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementStart(2, 'child-with-view'); elementStart(2, 'child-with-view');
text(3, 'Before projected'); text(3, 'Before projected');
elementStart(4, 'header', ['vcref', '']); elementStart(4, 'header', ['vcref', '']);
@ -1375,7 +1397,8 @@ describe('ViewContainerRef', () => {
let tplRef: any; let tplRef: any;
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template( template(
0, embeddedTemplate, 2, 1, null, null, ['foo', ''], templateRefExtractor); 0, embeddedTemplate, 2, 1, null, null, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementStart(2, 'child-with-selector'); elementStart(2, 'child-with-selector');
elementStart(3, 'header', ['vcref', '']); elementStart(3, 'header', ['vcref', '']);
text(4, 'blah'); text(4, 'blah');
@ -1428,7 +1451,8 @@ describe('ViewContainerRef', () => {
let tplRef: any; let tplRef: any;
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template( template(
0, embeddedTemplate, 2, 1, null, null, ['foo', ''], templateRefExtractor); 0, embeddedTemplate, 2, 1, null, null, ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
elementStart(2, 'child-with-selector'); elementStart(2, 'child-with-selector');
elementStart(3, 'footer', ['vcref', '']); elementStart(3, 'footer', ['vcref', '']);
text(4, 'blah'); text(4, 'blah');
@ -1533,7 +1557,8 @@ describe('ViewContainerRef', () => {
template: (rf: RenderFlags, cmp: SomeComponent) => { template: (rf: RenderFlags, cmp: SomeComponent) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
template( template(
0, SomeComponent_Template_0, 1, 1, null, [], ['foo', ''], templateRefExtractor); 0, SomeComponent_Template_0, 1, 1, null, [], ['foo', ''],
templateRefExtractor(TemplateRef, ElementRef));
element(2, 'hooks', ['vcref', '']); element(2, 'hooks', ['vcref', '']);
element(3, 'hooks'); element(3, 'hooks');
} }