feat(core): add `@Component.precompile` and `ComponentFactoryResolver`
Part to #9467 Closes #9543
This commit is contained in:
parent
9ed8f2d26e
commit
6c5b653593
|
@ -0,0 +1,18 @@
|
||||||
|
/**
|
||||||
|
* @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 {Component, ComponentFactoryResolver, Inject, OpaqueToken} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({selector: 'cmp', template: ''})
|
||||||
|
export class SomeComp {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'cmp-precompile', template: '', precompile: [SomeComp]})
|
||||||
|
export class CompWithPrecompile {
|
||||||
|
constructor(public cfr: ComponentFactoryResolver) {}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* @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 {DebugElement, ReflectiveInjector, getDebugNode, lockRunMode} from '@angular/core';
|
||||||
|
import {BROWSER_APP_PROVIDERS, By} from '@angular/platform-browser';
|
||||||
|
import {serverPlatform} from '@angular/platform-server';
|
||||||
|
|
||||||
|
import {SomeComp} from '../src/precompile';
|
||||||
|
import {CompWithPrecompileNgFactory} from '../src/precompile.ngfactory';
|
||||||
|
|
||||||
|
// Need to lock the mode explicitely as this test is not using Angular's testing framework.
|
||||||
|
lockRunMode();
|
||||||
|
|
||||||
|
describe('content projection', () => {
|
||||||
|
it('should support basic content projection', () => {
|
||||||
|
const appInjector =
|
||||||
|
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector);
|
||||||
|
var compWithPrecompile = CompWithPrecompileNgFactory.create(appInjector).instance;
|
||||||
|
var cf = compWithPrecompile.cfr.resolveComponentFactory(SomeComp);
|
||||||
|
expect(cf.componentType).toBe(SomeComp);
|
||||||
|
});
|
||||||
|
});
|
|
@ -24,6 +24,8 @@ export var ReflectorComponentResolver: typeof t.ReflectorComponentResolver =
|
||||||
r.ReflectorComponentResolver;
|
r.ReflectorComponentResolver;
|
||||||
export type AppElement = t.AppElement;
|
export type AppElement = t.AppElement;
|
||||||
export var AppElement: typeof t.AppElement = r.AppElement;
|
export var AppElement: typeof t.AppElement = r.AppElement;
|
||||||
|
export var CodegenComponentFactoryResolver: typeof t.CodegenComponentFactoryResolver =
|
||||||
|
r.CodegenComponentFactoryResolver;
|
||||||
export var AppView: typeof t.AppView = r.AppView;
|
export var AppView: typeof t.AppView = r.AppView;
|
||||||
export type DebugAppView<T> = t.DebugAppView<T>;
|
export type DebugAppView<T> = t.DebugAppView<T>;
|
||||||
export var DebugAppView: typeof t.DebugAppView = r.DebugAppView;
|
export var DebugAppView: typeof t.DebugAppView = r.DebugAppView;
|
||||||
|
|
|
@ -675,7 +675,7 @@ export class CompileTemplateMetadata {
|
||||||
export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||||
static create(
|
static create(
|
||||||
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
|
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
|
||||||
lifecycleHooks, providers, viewProviders, queries, viewQueries, template}: {
|
lifecycleHooks, providers, viewProviders, queries, viewQueries, precompile, template}: {
|
||||||
type?: CompileTypeMetadata,
|
type?: CompileTypeMetadata,
|
||||||
isComponent?: boolean,
|
isComponent?: boolean,
|
||||||
selector?: string,
|
selector?: string,
|
||||||
|
@ -691,6 +691,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||||
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
|
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
|
||||||
queries?: CompileQueryMetadata[],
|
queries?: CompileQueryMetadata[],
|
||||||
viewQueries?: CompileQueryMetadata[],
|
viewQueries?: CompileQueryMetadata[],
|
||||||
|
precompile?: CompileTypeMetadata[],
|
||||||
template?: CompileTemplateMetadata
|
template?: CompileTemplateMetadata
|
||||||
} = {}): CompileDirectiveMetadata {
|
} = {}): CompileDirectiveMetadata {
|
||||||
var hostListeners: {[key: string]: string} = {};
|
var hostListeners: {[key: string]: string} = {};
|
||||||
|
@ -743,6 +744,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||||
viewProviders: viewProviders,
|
viewProviders: viewProviders,
|
||||||
queries: queries,
|
queries: queries,
|
||||||
viewQueries: viewQueries,
|
viewQueries: viewQueries,
|
||||||
|
precompile: precompile,
|
||||||
template: template
|
template: template
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -761,12 +763,13 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||||
viewProviders: CompileProviderMetadata[];
|
viewProviders: CompileProviderMetadata[];
|
||||||
queries: CompileQueryMetadata[];
|
queries: CompileQueryMetadata[];
|
||||||
viewQueries: CompileQueryMetadata[];
|
viewQueries: CompileQueryMetadata[];
|
||||||
|
precompile: CompileTypeMetadata[];
|
||||||
|
|
||||||
template: CompileTemplateMetadata;
|
template: CompileTemplateMetadata;
|
||||||
constructor(
|
constructor(
|
||||||
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners,
|
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners,
|
||||||
hostProperties, hostAttributes, lifecycleHooks, providers, viewProviders, queries,
|
hostProperties, hostAttributes, lifecycleHooks, providers, viewProviders, queries,
|
||||||
viewQueries, template}: {
|
viewQueries, precompile, template}: {
|
||||||
type?: CompileTypeMetadata,
|
type?: CompileTypeMetadata,
|
||||||
isComponent?: boolean,
|
isComponent?: boolean,
|
||||||
selector?: string,
|
selector?: string,
|
||||||
|
@ -784,6 +787,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||||
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
|
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
|
||||||
queries?: CompileQueryMetadata[],
|
queries?: CompileQueryMetadata[],
|
||||||
viewQueries?: CompileQueryMetadata[],
|
viewQueries?: CompileQueryMetadata[],
|
||||||
|
precompile?: CompileTypeMetadata[],
|
||||||
template?: CompileTemplateMetadata
|
template?: CompileTemplateMetadata
|
||||||
} = {}) {
|
} = {}) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
@ -801,6 +805,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||||
this.viewProviders = _normalizeArray(viewProviders);
|
this.viewProviders = _normalizeArray(viewProviders);
|
||||||
this.queries = _normalizeArray(queries);
|
this.queries = _normalizeArray(queries);
|
||||||
this.viewQueries = _normalizeArray(viewQueries);
|
this.viewQueries = _normalizeArray(viewQueries);
|
||||||
|
this.precompile = _normalizeArray(precompile);
|
||||||
this.template = template;
|
this.template = template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,7 +832,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||||
providers: _arrayFromJson(data['providers'], metadataFromJson),
|
providers: _arrayFromJson(data['providers'], metadataFromJson),
|
||||||
viewProviders: _arrayFromJson(data['viewProviders'], metadataFromJson),
|
viewProviders: _arrayFromJson(data['viewProviders'], metadataFromJson),
|
||||||
queries: _arrayFromJson(data['queries'], CompileQueryMetadata.fromJson),
|
queries: _arrayFromJson(data['queries'], CompileQueryMetadata.fromJson),
|
||||||
viewQueries: _arrayFromJson(data['viewQueries'], CompileQueryMetadata.fromJson)
|
viewQueries: _arrayFromJson(data['viewQueries'], CompileQueryMetadata.fromJson),
|
||||||
|
precompile: _arrayFromJson(data['precompile'], CompileTypeMetadata.fromJson)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,7 +856,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||||
'providers': _arrayToJson(this.providers),
|
'providers': _arrayToJson(this.providers),
|
||||||
'viewProviders': _arrayToJson(this.viewProviders),
|
'viewProviders': _arrayToJson(this.viewProviders),
|
||||||
'queries': _arrayToJson(this.queries),
|
'queries': _arrayToJson(this.queries),
|
||||||
'viewQueries': _arrayToJson(this.viewQueries)
|
'viewQueries': _arrayToJson(this.viewQueries),
|
||||||
|
'precompile': _arrayToJson(this.precompile)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ export class DirectiveNormalizer {
|
||||||
viewProviders: directive.viewProviders,
|
viewProviders: directive.viewProviders,
|
||||||
queries: directive.queries,
|
queries: directive.queries,
|
||||||
viewQueries: directive.viewQueries,
|
viewQueries: directive.viewQueries,
|
||||||
|
precompile: directive.precompile,
|
||||||
template: normalizedTemplate
|
template: normalizedTemplate
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,8 @@ export class DirectiveResolver {
|
||||||
queries: mergedQueries,
|
queries: mergedQueries,
|
||||||
changeDetection: dm.changeDetection,
|
changeDetection: dm.changeDetection,
|
||||||
providers: dm.providers,
|
providers: dm.providers,
|
||||||
viewProviders: dm.viewProviders
|
viewProviders: dm.viewProviders,
|
||||||
|
precompile: dm.precompile
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {ChangeDetectionStrategy, ChangeDetectorRef, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
import {ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||||
|
|
||||||
import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppView, ChangeDetectorState, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, SecurityContext, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles, uninitialized} from '../core_private';
|
import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppView, ChangeDetectorState, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, SecurityContext, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles, uninitialized} from '../core_private';
|
||||||
|
|
||||||
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
||||||
import {assetUrl} from './util';
|
import {assetUrl} from './util';
|
||||||
|
@ -98,6 +98,16 @@ export class Identifiers {
|
||||||
moduleUrl: assetUrl('core', 'linker/template_ref'),
|
moduleUrl: assetUrl('core', 'linker/template_ref'),
|
||||||
runtime: impTemplateRef_
|
runtime: impTemplateRef_
|
||||||
});
|
});
|
||||||
|
static CodegenComponentFactoryResolver = new CompileIdentifierMetadata({
|
||||||
|
name: 'CodegenComponentFactoryResolver',
|
||||||
|
moduleUrl: assetUrl('core', 'linker/component_factory_resolver'),
|
||||||
|
runtime: CodegenComponentFactoryResolver
|
||||||
|
});
|
||||||
|
static ComponentFactoryResolver = new CompileIdentifierMetadata({
|
||||||
|
name: 'ComponentFactoryResolver',
|
||||||
|
moduleUrl: assetUrl('core', 'linker/component_factory_resolver'),
|
||||||
|
runtime: ComponentFactoryResolver
|
||||||
|
});
|
||||||
static ValueUnwrapper = new CompileIdentifierMetadata(
|
static ValueUnwrapper = new CompileIdentifierMetadata(
|
||||||
{name: 'ValueUnwrapper', moduleUrl: CD_MODULE_URL, runtime: impValueUnwrapper});
|
{name: 'ValueUnwrapper', moduleUrl: CD_MODULE_URL, runtime: impValueUnwrapper});
|
||||||
static Injector = new CompileIdentifierMetadata(
|
static Injector = new CompileIdentifierMetadata(
|
||||||
|
|
|
@ -99,6 +99,7 @@ export class CompileMetadataResolver {
|
||||||
var changeDetectionStrategy: any /** TODO #9100 */ = null;
|
var changeDetectionStrategy: any /** TODO #9100 */ = null;
|
||||||
var viewProviders: any[] /** TODO #9100 */ = [];
|
var viewProviders: any[] /** TODO #9100 */ = [];
|
||||||
var moduleUrl = staticTypeModuleUrl(directiveType);
|
var moduleUrl = staticTypeModuleUrl(directiveType);
|
||||||
|
var precompileTypes: cpl.CompileTypeMetadata[] = [];
|
||||||
if (dirMeta instanceof ComponentMetadata) {
|
if (dirMeta instanceof ComponentMetadata) {
|
||||||
assertArrayOfStrings('styles', dirMeta.styles);
|
assertArrayOfStrings('styles', dirMeta.styles);
|
||||||
var cmpMeta = <ComponentMetadata>dirMeta;
|
var cmpMeta = <ComponentMetadata>dirMeta;
|
||||||
|
@ -124,6 +125,10 @@ export class CompileMetadataResolver {
|
||||||
verifyNonBlankProviders(directiveType, dirMeta.viewProviders, 'viewProviders'));
|
verifyNonBlankProviders(directiveType, dirMeta.viewProviders, 'viewProviders'));
|
||||||
}
|
}
|
||||||
moduleUrl = componentModuleUrl(this._reflector, directiveType, cmpMeta);
|
moduleUrl = componentModuleUrl(this._reflector, directiveType, cmpMeta);
|
||||||
|
if (cmpMeta.precompile) {
|
||||||
|
precompileTypes = flattenArray(cmpMeta.precompile)
|
||||||
|
.map((cmp) => this.getTypeMetadata(cmp, staticTypeModuleUrl(cmp)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var providers: any[] /** TODO #9100 */ = [];
|
var providers: any[] /** TODO #9100 */ = [];
|
||||||
|
@ -152,7 +157,8 @@ export class CompileMetadataResolver {
|
||||||
providers: providers,
|
providers: providers,
|
||||||
viewProviders: viewProviders,
|
viewProviders: viewProviders,
|
||||||
queries: queries,
|
queries: queries,
|
||||||
viewQueries: viewQueries
|
viewQueries: viewQueries,
|
||||||
|
precompile: precompileTypes
|
||||||
});
|
});
|
||||||
this._directiveCache.set(directiveType, meta);
|
this._directiveCache.set(directiveType, meta);
|
||||||
}
|
}
|
||||||
|
@ -422,7 +428,7 @@ function flattenPipes(view: ViewMetadata, platformPipes: any[]): Type[] {
|
||||||
return pipes;
|
return pipes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function flattenArray(tree: any[], out: Array<Type|any[]>): void {
|
function flattenArray(tree: any[], out: Array<Type> = []): Array<Type> {
|
||||||
for (var i = 0; i < tree.length; i++) {
|
for (var i = 0; i < tree.length; i++) {
|
||||||
var item = resolveForwardRef(tree[i]);
|
var item = resolveForwardRef(tree[i]);
|
||||||
if (isArray(item)) {
|
if (isArray(item)) {
|
||||||
|
@ -431,6 +437,7 @@ function flattenArray(tree: any[], out: Array<Type|any[]>): void {
|
||||||
out.push(item);
|
out.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyNonBlankProviders(
|
function verifyNonBlankProviders(
|
||||||
|
|
|
@ -17,7 +17,7 @@ import * as o from './output/output_ast';
|
||||||
import {StyleCompiler, StylesCompileResult} from './style_compiler';
|
import {StyleCompiler, StylesCompileResult} from './style_compiler';
|
||||||
import {TemplateParser} from './template_parser';
|
import {TemplateParser} from './template_parser';
|
||||||
import {assetUrl} from './util';
|
import {assetUrl} from './util';
|
||||||
import {ViewCompileResult, ViewCompiler} from './view_compiler/view_compiler';
|
import {ComponentFactoryDependency, ViewCompileResult, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
|
||||||
import {XHR} from './xhr';
|
import {XHR} from './xhr';
|
||||||
|
|
||||||
var _COMPONENT_FACTORY_IDENTIFIER = new CompileIdentifierMetadata({
|
var _COMPONENT_FACTORY_IDENTIFIER = new CompileIdentifierMetadata({
|
||||||
|
@ -57,7 +57,7 @@ export class OfflineCompiler {
|
||||||
}
|
}
|
||||||
var statements: o.DeclareVarStmt[] = [];
|
var statements: o.DeclareVarStmt[] = [];
|
||||||
var exportedVars: string[] = [];
|
var exportedVars: string[] = [];
|
||||||
var moduleUrl = _templateModuleUrl(components[0].component);
|
var moduleUrl = _ngfactoryModuleUrl(components[0].component.type);
|
||||||
components.forEach(componentWithDirs => {
|
components.forEach(componentWithDirs => {
|
||||||
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
|
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
|
||||||
_assertComponent(compMeta);
|
_assertComponent(compMeta);
|
||||||
|
@ -67,7 +67,7 @@ export class OfflineCompiler {
|
||||||
|
|
||||||
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||||
var hostViewFactoryVar = this._compileComponent(hostMeta, [compMeta], [], statements);
|
var hostViewFactoryVar = this._compileComponent(hostMeta, [compMeta], [], statements);
|
||||||
var compFactoryVar = `${compMeta.type.name}NgFactory`;
|
var compFactoryVar = _componentFactoryName(compMeta.type);
|
||||||
statements.push(
|
statements.push(
|
||||||
o.variable(compFactoryVar)
|
o.variable(compFactoryVar)
|
||||||
.set(o.importExpr(_COMPONENT_FACTORY_IDENTIFIER, [o.importType(compMeta.type)])
|
.set(o.importExpr(_COMPONENT_FACTORY_IDENTIFIER, [o.importType(compMeta.type)])
|
||||||
|
@ -129,8 +129,14 @@ export class OfflineCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[] {
|
function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[] {
|
||||||
compileResult.dependencies.forEach(
|
compileResult.dependencies.forEach((dep) => {
|
||||||
(dep) => { dep.factoryPlaceholder.moduleUrl = _templateModuleUrl(dep.comp); });
|
if (dep instanceof ViewFactoryDependency) {
|
||||||
|
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp.type);
|
||||||
|
} else if (dep instanceof ComponentFactoryDependency) {
|
||||||
|
dep.placeholder.name = _componentFactoryName(dep.comp);
|
||||||
|
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp);
|
||||||
|
}
|
||||||
|
});
|
||||||
return compileResult.statements;
|
return compileResult.statements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,11 +151,15 @@ function _resolveStyleStatements(
|
||||||
return compileResult.statements;
|
return compileResult.statements;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _templateModuleUrl(comp: CompileDirectiveMetadata): string {
|
function _ngfactoryModuleUrl(comp: CompileIdentifierMetadata): string {
|
||||||
var urlWithSuffix = _splitSuffix(comp.type.moduleUrl);
|
var urlWithSuffix = _splitSuffix(comp.moduleUrl);
|
||||||
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
|
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _componentFactoryName(comp: CompileIdentifierMetadata): string {
|
||||||
|
return `${comp.name}NgFactory`;
|
||||||
|
}
|
||||||
|
|
||||||
function _stylesModuleUrl(stylesheetUrl: string, shim: boolean, suffix: string): string {
|
function _stylesModuleUrl(stylesheetUrl: string, shim: boolean, suffix: string): string {
|
||||||
return shim ? `${stylesheetUrl}.shim${suffix}` : `${stylesheetUrl}${suffix}`;
|
return shim ? `${stylesheetUrl}.shim${suffix}` : `${stylesheetUrl}${suffix}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {PromiseWrapper} from '../src/facade/async';
|
||||||
import {createHostComponentMeta, CompileDirectiveMetadata, CompilePipeMetadata, CompileIdentifierMetadata} from './compile_metadata';
|
import {createHostComponentMeta, CompileDirectiveMetadata, CompilePipeMetadata, CompileIdentifierMetadata} from './compile_metadata';
|
||||||
import {TemplateAst,} from './template_ast';
|
import {TemplateAst,} from './template_ast';
|
||||||
import {StyleCompiler, StylesCompileDependency, StylesCompileResult} from './style_compiler';
|
import {StyleCompiler, StylesCompileDependency, StylesCompileResult} from './style_compiler';
|
||||||
import {ViewCompiler} from './view_compiler/view_compiler';
|
import {ViewCompiler, ViewFactoryDependency, ComponentFactoryDependency} from './view_compiler/view_compiler';
|
||||||
import {TemplateParser} from './template_parser';
|
import {TemplateParser} from './template_parser';
|
||||||
import {DirectiveNormalizer} from './directive_normalizer';
|
import {DirectiveNormalizer} from './directive_normalizer';
|
||||||
import {CompileMetadataResolver} from './metadata_resolver';
|
import {CompileMetadataResolver} from './metadata_resolver';
|
||||||
|
@ -37,7 +37,6 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||||
private _styleCache: Map<string, Promise<string>> = new Map<string, Promise<string>>();
|
private _styleCache: Map<string, Promise<string>> = new Map<string, Promise<string>>();
|
||||||
private _hostCacheKeys = new Map<Type, any>();
|
private _hostCacheKeys = new Map<Type, any>();
|
||||||
private _compiledTemplateCache = new Map<any, CompiledTemplate>();
|
private _compiledTemplateCache = new Map<any, CompiledTemplate>();
|
||||||
private _compiledTemplateDone = new Map<any, Promise<CompiledTemplate>>();
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _metadataResolver: CompileMetadataResolver,
|
private _metadataResolver: CompileMetadataResolver,
|
||||||
|
@ -50,43 +49,38 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||||
return PromiseWrapper.reject(
|
return PromiseWrapper.reject(
|
||||||
new BaseException(`Cannot resolve component using '${component}'.`), null);
|
new BaseException(`Cannot resolve component using '${component}'.`), null);
|
||||||
}
|
}
|
||||||
|
return this._loadAndCompileHostComponent(<Type>component).done;
|
||||||
|
}
|
||||||
|
|
||||||
let componentType = <Type>component;
|
clearCache(): void {
|
||||||
|
this._styleCache.clear();
|
||||||
|
this._compiledTemplateCache.clear();
|
||||||
|
this._hostCacheKeys.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _loadAndCompileHostComponent(componentType: Type): CompileHostTemplate {
|
||||||
var compMeta: CompileDirectiveMetadata =
|
var compMeta: CompileDirectiveMetadata =
|
||||||
this._metadataResolver.getDirectiveMetadata(componentType);
|
this._metadataResolver.getDirectiveMetadata(componentType);
|
||||||
var hostCacheKey = this._hostCacheKeys.get(componentType);
|
var hostCacheKey = this._hostCacheKeys.get(compMeta.type.runtime);
|
||||||
if (isBlank(hostCacheKey)) {
|
if (isBlank(hostCacheKey)) {
|
||||||
hostCacheKey = new Object();
|
hostCacheKey = new Object();
|
||||||
this._hostCacheKeys.set(componentType, hostCacheKey);
|
this._hostCacheKeys.set(compMeta.type.runtime, hostCacheKey);
|
||||||
assertComponent(compMeta);
|
assertComponent(compMeta);
|
||||||
var hostMeta: CompileDirectiveMetadata =
|
var hostMeta: CompileDirectiveMetadata =
|
||||||
createHostComponentMeta(compMeta.type, compMeta.selector);
|
createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||||
|
|
||||||
this._loadAndCompileComponent(hostCacheKey, hostMeta, [compMeta], [], []);
|
this._loadAndCompileComponent(hostCacheKey, hostMeta, [compMeta], [], []);
|
||||||
}
|
}
|
||||||
return this._compiledTemplateDone.get(hostCacheKey)
|
var compTemplate = this._compiledTemplateCache.get(hostCacheKey);
|
||||||
.then(
|
return new CompileHostTemplate(compTemplate, compMeta);
|
||||||
(compiledTemplate: CompiledTemplate) => new ComponentFactory(
|
|
||||||
compMeta.selector, compiledTemplate.viewFactory, componentType));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCache(): void {
|
|
||||||
this._styleCache.clear();
|
|
||||||
this._compiledTemplateCache.clear();
|
|
||||||
this._compiledTemplateDone.clear();
|
|
||||||
this._hostCacheKeys.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private _loadAndCompileComponent(
|
private _loadAndCompileComponent(
|
||||||
cacheKey: any, compMeta: CompileDirectiveMetadata, viewDirectives: CompileDirectiveMetadata[],
|
cacheKey: any, compMeta: CompileDirectiveMetadata, viewDirectives: CompileDirectiveMetadata[],
|
||||||
pipes: CompilePipeMetadata[], compilingComponentsPath: any[]): CompiledTemplate {
|
pipes: CompilePipeMetadata[], compilingComponentsPath: any[]): CompiledTemplate {
|
||||||
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
|
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
|
||||||
var done = this._compiledTemplateDone.get(cacheKey);
|
|
||||||
if (isBlank(compiledTemplate)) {
|
if (isBlank(compiledTemplate)) {
|
||||||
compiledTemplate = new CompiledTemplate();
|
let done =
|
||||||
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
|
|
||||||
done =
|
|
||||||
PromiseWrapper
|
PromiseWrapper
|
||||||
.all([<any>this._compileComponentStyles(compMeta)].concat(viewDirectives.map(
|
.all([<any>this._compileComponentStyles(compMeta)].concat(viewDirectives.map(
|
||||||
dirMeta => this._templateNormalizer.normalizeDirective(dirMeta))))
|
dirMeta => this._templateNormalizer.normalizeDirective(dirMeta))))
|
||||||
|
@ -103,7 +97,8 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||||
childPromises));
|
childPromises));
|
||||||
return PromiseWrapper.all(childPromises).then((_) => { return compiledTemplate; });
|
return PromiseWrapper.all(childPromises).then((_) => { return compiledTemplate; });
|
||||||
});
|
});
|
||||||
this._compiledTemplateDone.set(cacheKey, done);
|
compiledTemplate = new CompiledTemplate(done);
|
||||||
|
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
|
||||||
}
|
}
|
||||||
return compiledTemplate;
|
return compiledTemplate;
|
||||||
}
|
}
|
||||||
|
@ -116,26 +111,32 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||||
compMeta, parsedTemplate,
|
compMeta, parsedTemplate,
|
||||||
new ir.ExternalExpr(new CompileIdentifierMetadata({runtime: styles})), pipes);
|
new ir.ExternalExpr(new CompileIdentifierMetadata({runtime: styles})), pipes);
|
||||||
compileResult.dependencies.forEach((dep) => {
|
compileResult.dependencies.forEach((dep) => {
|
||||||
var childCompilingComponentsPath = ListWrapper.clone(compilingComponentsPath);
|
if (dep instanceof ViewFactoryDependency) {
|
||||||
|
let childCompilingComponentsPath = ListWrapper.clone(compilingComponentsPath);
|
||||||
|
let childCacheKey = dep.comp.type.runtime;
|
||||||
|
let childViewDirectives: CompileDirectiveMetadata[] =
|
||||||
|
this._metadataResolver.getViewDirectivesMetadata(dep.comp.type.runtime);
|
||||||
|
let childViewPipes: CompilePipeMetadata[] =
|
||||||
|
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
|
||||||
|
let childIsRecursive = childCompilingComponentsPath.indexOf(childCacheKey) > -1 ||
|
||||||
|
childViewDirectives.some(
|
||||||
|
dir => childCompilingComponentsPath.indexOf(dir.type.runtime) > -1);
|
||||||
|
childCompilingComponentsPath.push(childCacheKey);
|
||||||
|
|
||||||
var childCacheKey = dep.comp.type.runtime;
|
let childComp = this._loadAndCompileComponent(
|
||||||
var childViewDirectives: CompileDirectiveMetadata[] =
|
dep.comp.type.runtime, dep.comp, childViewDirectives, childViewPipes,
|
||||||
this._metadataResolver.getViewDirectivesMetadata(dep.comp.type.runtime);
|
childCompilingComponentsPath);
|
||||||
var childViewPipes: CompilePipeMetadata[] =
|
dep.placeholder.runtime = childComp.proxyViewFactory;
|
||||||
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
|
dep.placeholder.name = `viewFactory_${dep.comp.type.name}`;
|
||||||
var childIsRecursive = childCompilingComponentsPath.indexOf(childCacheKey) > -1 ||
|
if (!childIsRecursive) {
|
||||||
childViewDirectives.some(
|
// Only wait for a child if it is not a cycle
|
||||||
dir => childCompilingComponentsPath.indexOf(dir.type.runtime) > -1);
|
childPromises.push(childComp.done);
|
||||||
childCompilingComponentsPath.push(childCacheKey);
|
}
|
||||||
|
} else if (dep instanceof ComponentFactoryDependency) {
|
||||||
var childComp = this._loadAndCompileComponent(
|
let childComp = this._loadAndCompileHostComponent(dep.comp.runtime);
|
||||||
dep.comp.type.runtime, dep.comp, childViewDirectives, childViewPipes,
|
dep.placeholder.runtime = childComp.componentFactory;
|
||||||
childCompilingComponentsPath);
|
dep.placeholder.name = `compFactory_${dep.comp.name}`;
|
||||||
dep.factoryPlaceholder.runtime = childComp.proxyViewFactory;
|
childPromises.push(childComp.done);
|
||||||
dep.factoryPlaceholder.name = `viewFactory_${dep.comp.type.name}`;
|
|
||||||
if (!childIsRecursive) {
|
|
||||||
// Only wait for a child if it is not a cycle
|
|
||||||
childPromises.push(this._compiledTemplateDone.get(childCacheKey));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var factory: any;
|
var factory: any;
|
||||||
|
@ -198,16 +199,27 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CompileHostTemplate {
|
||||||
|
componentFactory: ComponentFactory<any>;
|
||||||
|
done: Promise<ComponentFactory<any>>;
|
||||||
|
constructor(_template: CompiledTemplate, compMeta: CompileDirectiveMetadata) {
|
||||||
|
this.componentFactory = new ComponentFactory<any>(
|
||||||
|
compMeta.selector, _template.proxyViewFactory, compMeta.type.runtime);
|
||||||
|
this.done = _template.done.then((_) => this.componentFactory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CompiledTemplate {
|
class CompiledTemplate {
|
||||||
viewFactory: Function = null;
|
private _viewFactory: Function = null;
|
||||||
proxyViewFactory: Function;
|
proxyViewFactory: Function;
|
||||||
constructor() {
|
constructor(public done: Promise<CompiledTemplate>) {
|
||||||
this.proxyViewFactory =
|
this.proxyViewFactory =
|
||||||
(viewUtils: any /** TODO #9100 */, childInjector: any /** TODO #9100 */,
|
(viewUtils: any /** TODO #9100 */, childInjector: any /** TODO #9100 */,
|
||||||
contextEl: any /** TODO #9100 */) => this.viewFactory(viewUtils, childInjector, contextEl);
|
contextEl: any /** TODO #9100 */) =>
|
||||||
|
this._viewFactory(viewUtils, childInjector, contextEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
init(viewFactory: Function) { this.viewFactory = viewFactory; }
|
init(viewFactory: Function) { this._viewFactory = viewFactory; }
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertComponent(meta: CompileDirectiveMetadata) {
|
function assertComponent(meta: CompileDirectiveMetadata) {
|
||||||
|
|
|
@ -91,6 +91,28 @@ export class CompileElement extends CompileNode {
|
||||||
this._instances.add(identifierToken(Identifiers.AppElement), this.appElement);
|
this._instances.add(identifierToken(Identifiers.AppElement), this.appElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public createComponentFactoryResolver(precompileComponent: CompileIdentifierMetadata[]) {
|
||||||
|
if (!precompileComponent || precompileComponent.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var createComponentFactoryResolverExpr =
|
||||||
|
o.importExpr(Identifiers.CodegenComponentFactoryResolver).instantiate([
|
||||||
|
o.literalArr(precompileComponent.map(
|
||||||
|
(precompiledComponent) => o.importExpr(precompiledComponent))),
|
||||||
|
injectFromViewParentInjector(identifierToken(Identifiers.ComponentFactoryResolver), false)
|
||||||
|
]);
|
||||||
|
var provider = new CompileProviderMetadata({
|
||||||
|
token: identifierToken(Identifiers.ComponentFactoryResolver),
|
||||||
|
useValue: createComponentFactoryResolverExpr
|
||||||
|
});
|
||||||
|
// Add ComponentFactoryResolver as first provider as it does not have deps on other providers
|
||||||
|
// ProviderAstType.PrivateService as only the component and its view can see it,
|
||||||
|
// but nobody else
|
||||||
|
this._resolvedProvidersArray.unshift(new ProviderAst(
|
||||||
|
provider.token, false, true, [provider], ProviderAstType.PrivateService,
|
||||||
|
this.sourceAst.sourceSpan));
|
||||||
|
}
|
||||||
|
|
||||||
setComponentView(compViewExpr: o.Expression) {
|
setComponentView(compViewExpr: o.Expression) {
|
||||||
this._compViewExpr = compViewExpr;
|
this._compViewExpr = compViewExpr;
|
||||||
this.contentNodesByNgContentIndex =
|
this.contentNodesByNgContentIndex =
|
||||||
|
@ -167,21 +189,20 @@ export class CompileElement extends CompileNode {
|
||||||
queriesWithReads,
|
queriesWithReads,
|
||||||
queriesForProvider.map(query => new _QueryWithRead(query, resolvedProvider.token)));
|
queriesForProvider.map(query => new _QueryWithRead(query, resolvedProvider.token)));
|
||||||
});
|
});
|
||||||
StringMapWrapper.forEach(
|
StringMapWrapper.forEach(this.referenceTokens, (_: CompileTokenMetadata, varName: string) => {
|
||||||
this.referenceTokens, (_: any /** TODO #9100 */, varName: any /** TODO #9100 */) => {
|
var token = this.referenceTokens[varName];
|
||||||
var token = this.referenceTokens[varName];
|
var varValue: o.Expression;
|
||||||
var varValue: any /** TODO #9100 */;
|
if (isPresent(token)) {
|
||||||
if (isPresent(token)) {
|
varValue = this._instances.get(token);
|
||||||
varValue = this._instances.get(token);
|
} else {
|
||||||
} else {
|
varValue = this.renderNode;
|
||||||
varValue = this.renderNode;
|
}
|
||||||
}
|
this.view.locals.set(varName, varValue);
|
||||||
this.view.locals.set(varName, varValue);
|
var varToken = new CompileTokenMetadata({value: varName});
|
||||||
var varToken = new CompileTokenMetadata({value: varName});
|
ListWrapper.addAll(
|
||||||
ListWrapper.addAll(
|
queriesWithReads,
|
||||||
queriesWithReads,
|
this._getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken)));
|
||||||
this._getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken)));
|
});
|
||||||
});
|
|
||||||
queriesWithReads.forEach((queryWithRead) => {
|
queriesWithReads.forEach((queryWithRead) => {
|
||||||
var value: o.Expression;
|
var value: o.Expression;
|
||||||
if (isPresent(queryWithRead.read.identifier)) {
|
if (isPresent(queryWithRead.read.identifier)) {
|
||||||
|
@ -285,7 +306,7 @@ export class CompileElement extends CompileNode {
|
||||||
|
|
||||||
private _getLocalDependency(
|
private _getLocalDependency(
|
||||||
requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata): o.Expression {
|
requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata): o.Expression {
|
||||||
var result: any /** TODO #9100 */ = null;
|
var result: o.Expression = null;
|
||||||
// constructor content query
|
// constructor content query
|
||||||
if (isBlank(result) && isPresent(dep.query)) {
|
if (isBlank(result) && isPresent(dep.query)) {
|
||||||
result = this._addQuery(dep.query, null).queryList;
|
result = this._addQuery(dep.query, null).queryList;
|
||||||
|
@ -330,7 +351,7 @@ export class CompileElement extends CompileNode {
|
||||||
private _getDependency(requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata):
|
private _getDependency(requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata):
|
||||||
o.Expression {
|
o.Expression {
|
||||||
var currElement: CompileElement = this;
|
var currElement: CompileElement = this;
|
||||||
var result: any /** TODO #9100 */ = null;
|
var result: o.Expression = null;
|
||||||
if (dep.isValue) {
|
if (dep.isValue) {
|
||||||
result = o.literal(dep.value);
|
result = o.literal(dep.value);
|
||||||
}
|
}
|
||||||
|
@ -357,7 +378,7 @@ export class CompileElement extends CompileNode {
|
||||||
function createInjectInternalCondition(
|
function createInjectInternalCondition(
|
||||||
nodeIndex: number, childNodeCount: number, provider: ProviderAst,
|
nodeIndex: number, childNodeCount: number, provider: ProviderAst,
|
||||||
providerExpr: o.Expression): o.Statement {
|
providerExpr: o.Expression): o.Statement {
|
||||||
var indexCondition: any /** TODO #9100 */;
|
var indexCondition: o.Expression;
|
||||||
if (childNodeCount > 0) {
|
if (childNodeCount > 0) {
|
||||||
indexCondition = o.literal(nodeIndex)
|
indexCondition = o.literal(nodeIndex)
|
||||||
.lowerEquals(InjectMethodVars.requestNodeIndex)
|
.lowerEquals(InjectMethodVars.requestNodeIndex)
|
||||||
|
@ -375,8 +396,8 @@ function createProviderProperty(
|
||||||
propName: string, provider: ProviderAst, providerValueExpressions: o.Expression[],
|
propName: string, provider: ProviderAst, providerValueExpressions: o.Expression[],
|
||||||
isMulti: boolean, isEager: boolean, compileElement: CompileElement): o.Expression {
|
isMulti: boolean, isEager: boolean, compileElement: CompileElement): o.Expression {
|
||||||
var view = compileElement.view;
|
var view = compileElement.view;
|
||||||
var resolvedProviderValueExpr: any /** TODO #9100 */;
|
var resolvedProviderValueExpr: o.Expression;
|
||||||
var type: any /** TODO #9100 */;
|
var type: o.Type;
|
||||||
if (isMulti) {
|
if (isMulti) {
|
||||||
resolvedProviderValueExpr = o.literalArr(providerValueExpressions);
|
resolvedProviderValueExpr = o.literalArr(providerValueExpressions);
|
||||||
type = new o.ArrayType(o.DYNAMIC_TYPE);
|
type = new o.ArrayType(o.DYNAMIC_TYPE);
|
||||||
|
@ -421,8 +442,8 @@ class _ValueOutputAstTransformer extends ValueTransformer {
|
||||||
return o.literalArr(arr.map(value => visitValue(value, this, context)));
|
return o.literalArr(arr.map(value => visitValue(value, this, context)));
|
||||||
}
|
}
|
||||||
visitStringMap(map: {[key: string]: any}, context: any): o.Expression {
|
visitStringMap(map: {[key: string]: any}, context: any): o.Expression {
|
||||||
var entries: any[] /** TODO #9100 */ = [];
|
var entries: Array<string|o.Expression>[] = [];
|
||||||
StringMapWrapper.forEach(map, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => {
|
StringMapWrapper.forEach(map, (value: any, key: string) => {
|
||||||
entries.push([key, visitValue(value, this, context)]);
|
entries.push([key, visitValue(value, this, context)]);
|
||||||
});
|
});
|
||||||
return o.literalMap(entries);
|
return o.literalMap(entries);
|
||||||
|
|
|
@ -9,22 +9,18 @@
|
||||||
import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
|
import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
|
||||||
|
|
||||||
import {ViewType, isDefaultChangeDetectionStrategy} from '../../core_private';
|
import {ViewType, isDefaultChangeDetectionStrategy} from '../../core_private';
|
||||||
|
import {AnimationCompiler} from '../animation/animation_compiler';
|
||||||
|
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileTokenMetadata, CompileTypeMetadata} from '../compile_metadata';
|
||||||
import {ListWrapper, SetWrapper, StringMapWrapper} from '../facade/collection';
|
import {ListWrapper, SetWrapper, StringMapWrapper} from '../facade/collection';
|
||||||
import {StringWrapper, isPresent} from '../facade/lang';
|
import {StringWrapper, isPresent} from '../facade/lang';
|
||||||
import {Identifiers, identifierToken} from '../identifiers';
|
import {Identifiers, identifierToken} from '../identifiers';
|
||||||
import * as o from '../output/output_ast';
|
import * as o from '../output/output_ast';
|
||||||
|
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ProviderAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_ast';
|
||||||
|
|
||||||
import {CompileElement, CompileNode} from './compile_element';
|
import {CompileElement, CompileNode} from './compile_element';
|
||||||
import {CompileView} from './compile_view';
|
import {CompileView} from './compile_view';
|
||||||
import {ChangeDetectionStrategyEnum, DetectChangesVars, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants';
|
import {ChangeDetectionStrategyEnum, DetectChangesVars, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants';
|
||||||
|
import {createDiTokenExpression, createFlatArray, getViewFactoryName} from './util';
|
||||||
import {TemplateAst, TemplateAstVisitor, NgContentAst, EmbeddedTemplateAst, ElementAst, ReferenceAst, VariableAst, BoundEventAst, BoundElementPropertyAst, AttrAst, BoundTextAst, TextAst, DirectiveAst, BoundDirectivePropertyAst, templateVisitAll,} from '../template_ast';
|
|
||||||
|
|
||||||
import {getViewFactoryName, createFlatArray, createDiTokenExpression} from './util';
|
|
||||||
|
|
||||||
import {CompileIdentifierMetadata, CompileDirectiveMetadata, CompileTokenMetadata} from '../compile_metadata';
|
|
||||||
|
|
||||||
import {AnimationCompiler} from '../animation/animation_compiler';
|
|
||||||
|
|
||||||
const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
||||||
const CLASS_ATTR = 'class';
|
const CLASS_ATTR = 'class';
|
||||||
|
@ -34,15 +30,20 @@ const NG_CONTAINER_TAG = 'ng-container';
|
||||||
var parentRenderNodeVar = o.variable('parentRenderNode');
|
var parentRenderNodeVar = o.variable('parentRenderNode');
|
||||||
var rootSelectorVar = o.variable('rootSelector');
|
var rootSelectorVar = o.variable('rootSelector');
|
||||||
|
|
||||||
export class ViewCompileDependency {
|
export class ViewFactoryDependency {
|
||||||
constructor(
|
constructor(
|
||||||
public comp: CompileDirectiveMetadata, public factoryPlaceholder: CompileIdentifierMetadata) {
|
public comp: CompileDirectiveMetadata, public placeholder: CompileIdentifierMetadata) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ComponentFactoryDependency {
|
||||||
|
constructor(
|
||||||
|
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function buildView(
|
export function buildView(
|
||||||
view: CompileView, template: TemplateAst[],
|
view: CompileView, template: TemplateAst[],
|
||||||
targetDependencies: ViewCompileDependency[]): number {
|
targetDependencies: Array<ViewFactoryDependency|ComponentFactoryDependency>): number {
|
||||||
var builderVisitor = new ViewBuilderVisitor(view, targetDependencies);
|
var builderVisitor = new ViewBuilderVisitor(view, targetDependencies);
|
||||||
templateVisitAll(
|
templateVisitAll(
|
||||||
builderVisitor, template,
|
builderVisitor, template,
|
||||||
|
@ -65,7 +66,9 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
|
||||||
|
|
||||||
private _animationCompiler = new AnimationCompiler();
|
private _animationCompiler = new AnimationCompiler();
|
||||||
|
|
||||||
constructor(public view: CompileView, public targetDependencies: ViewCompileDependency[]) {}
|
constructor(
|
||||||
|
public view: CompileView,
|
||||||
|
public targetDependencies: Array<ViewFactoryDependency|ComponentFactoryDependency>) {}
|
||||||
|
|
||||||
private _isRootNode(parent: CompileElement): boolean { return parent.view !== this.view; }
|
private _isRootNode(parent: CompileElement): boolean { return parent.view !== this.view; }
|
||||||
|
|
||||||
|
@ -203,9 +206,17 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
|
||||||
this.view.nodes.push(compileElement);
|
this.view.nodes.push(compileElement);
|
||||||
var compViewExpr: o.ReadVarExpr = null;
|
var compViewExpr: o.ReadVarExpr = null;
|
||||||
if (isPresent(component)) {
|
if (isPresent(component)) {
|
||||||
var nestedComponentIdentifier =
|
let nestedComponentIdentifier =
|
||||||
new CompileIdentifierMetadata({name: getViewFactoryName(component, 0)});
|
new CompileIdentifierMetadata({name: getViewFactoryName(component, 0)});
|
||||||
this.targetDependencies.push(new ViewCompileDependency(component, nestedComponentIdentifier));
|
this.targetDependencies.push(new ViewFactoryDependency(component, nestedComponentIdentifier));
|
||||||
|
let precompileComponentIdentifiers =
|
||||||
|
component.precompile.map((precompileComp: CompileIdentifierMetadata) => {
|
||||||
|
var id = new CompileIdentifierMetadata({name: precompileComp.name});
|
||||||
|
this.targetDependencies.push(new ComponentFactoryDependency(precompileComp, id));
|
||||||
|
return id;
|
||||||
|
});
|
||||||
|
compileElement.createComponentFactoryResolver(precompileComponentIdentifiers);
|
||||||
|
|
||||||
compViewExpr = o.variable(`compView_${nodeIndex}`); // fix highlighting: `
|
compViewExpr = o.variable(`compView_${nodeIndex}`); // fix highlighting: `
|
||||||
compileElement.setComponentView(compViewExpr);
|
compileElement.setComponentView(compViewExpr);
|
||||||
this.view.createMethod.addStmt(
|
this.view.createMethod.addStmt(
|
||||||
|
|
|
@ -17,12 +17,14 @@ import {TemplateAst} from '../template_ast';
|
||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileView} from './compile_view';
|
import {CompileView} from './compile_view';
|
||||||
import {bindView} from './view_binder';
|
import {bindView} from './view_binder';
|
||||||
import {ViewCompileDependency, buildView, finishView} from './view_builder';
|
import {ComponentFactoryDependency, ViewFactoryDependency, buildView, finishView} from './view_builder';
|
||||||
|
|
||||||
|
export {ComponentFactoryDependency, ViewFactoryDependency} from './view_builder';
|
||||||
|
|
||||||
export class ViewCompileResult {
|
export class ViewCompileResult {
|
||||||
constructor(
|
constructor(
|
||||||
public statements: o.Statement[], public viewFactoryVar: string,
|
public statements: o.Statement[], public viewFactoryVar: string,
|
||||||
public dependencies: ViewCompileDependency[]) {}
|
public dependencies: Array<ViewFactoryDependency|ComponentFactoryDependency>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -33,9 +35,9 @@ export class ViewCompiler {
|
||||||
compileComponent(
|
compileComponent(
|
||||||
component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression,
|
component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression,
|
||||||
pipes: CompilePipeMetadata[]): ViewCompileResult {
|
pipes: CompilePipeMetadata[]): ViewCompileResult {
|
||||||
var dependencies: any[] /** TODO #9100 */ = [];
|
var dependencies: Array<ViewFactoryDependency|ComponentFactoryDependency> = [];
|
||||||
var compiledAnimations = this._animationCompiler.compileComponent(component);
|
var compiledAnimations = this._animationCompiler.compileComponent(component);
|
||||||
var statements: any[] /** TODO #9100 */ = [];
|
var statements: o.Statement[] = [];
|
||||||
compiledAnimations.map(entry => {
|
compiledAnimations.map(entry => {
|
||||||
statements.push(entry.statesMapStatement);
|
statements.push(entry.statesMapStatement);
|
||||||
statements.push(entry.fnStatement);
|
statements.push(entry.fnStatement);
|
||||||
|
|
|
@ -51,7 +51,8 @@ export class MockDirectiveResolver extends DirectiveResolver {
|
||||||
queries: dm.queries,
|
queries: dm.queries,
|
||||||
changeDetection: dm.changeDetection,
|
changeDetection: dm.changeDetection,
|
||||||
providers: providers,
|
providers: providers,
|
||||||
viewProviders: viewProviders
|
viewProviders: viewProviders,
|
||||||
|
precompile: dm.precompile
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import * as console from './src/console';
|
||||||
import * as debug from './src/debug/debug_renderer';
|
import * as debug from './src/debug/debug_renderer';
|
||||||
import * as provider_util from './src/di/provider_util';
|
import * as provider_util from './src/di/provider_util';
|
||||||
import * as reflective_provider from './src/di/reflective_provider';
|
import * as reflective_provider from './src/di/reflective_provider';
|
||||||
|
import * as component_factory_resolver from './src/linker/component_factory_resolver';
|
||||||
import * as component_resolver from './src/linker/component_resolver';
|
import * as component_resolver from './src/linker/component_resolver';
|
||||||
import * as debug_context from './src/linker/debug_context';
|
import * as debug_context from './src/linker/debug_context';
|
||||||
import * as element from './src/linker/element';
|
import * as element from './src/linker/element';
|
||||||
|
@ -52,6 +53,8 @@ export declare namespace __core_private_types__ {
|
||||||
export type ReflectorReader = reflector_reader.ReflectorReader;
|
export type ReflectorReader = reflector_reader.ReflectorReader;
|
||||||
export var ReflectorReader: typeof reflector_reader.ReflectorReader;
|
export var ReflectorReader: typeof reflector_reader.ReflectorReader;
|
||||||
export var ReflectorComponentResolver: typeof component_resolver.ReflectorComponentResolver;
|
export var ReflectorComponentResolver: typeof component_resolver.ReflectorComponentResolver;
|
||||||
|
export var CodegenComponentFactoryResolver:
|
||||||
|
typeof component_factory_resolver.CodegenComponentFactoryResolver;
|
||||||
export type AppElement = element.AppElement;
|
export type AppElement = element.AppElement;
|
||||||
export var AppElement: typeof element.AppElement;
|
export var AppElement: typeof element.AppElement;
|
||||||
export var AppView: typeof view.AppView;
|
export var AppView: typeof view.AppView;
|
||||||
|
@ -141,6 +144,7 @@ export var __core_private__ = {
|
||||||
LIFECYCLE_HOOKS_VALUES: lifecycle_hooks.LIFECYCLE_HOOKS_VALUES,
|
LIFECYCLE_HOOKS_VALUES: lifecycle_hooks.LIFECYCLE_HOOKS_VALUES,
|
||||||
ReflectorReader: reflector_reader.ReflectorReader,
|
ReflectorReader: reflector_reader.ReflectorReader,
|
||||||
ReflectorComponentResolver: component_resolver.ReflectorComponentResolver,
|
ReflectorComponentResolver: component_resolver.ReflectorComponentResolver,
|
||||||
|
CodegenComponentFactoryResolver: component_factory_resolver.CodegenComponentFactoryResolver,
|
||||||
AppElement: element.AppElement,
|
AppElement: element.AppElement,
|
||||||
AppView: view.AppView,
|
AppView: view.AppView,
|
||||||
DebugAppView: view.DebugAppView,
|
DebugAppView: view.DebugAppView,
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {Type} from '../src/facade/lang';
|
||||||
import {APPLICATION_CORE_PROVIDERS} from './application_ref';
|
import {APPLICATION_CORE_PROVIDERS} from './application_ref';
|
||||||
import {APP_ID_RANDOM_PROVIDER} from './application_tokens';
|
import {APP_ID_RANDOM_PROVIDER} from './application_tokens';
|
||||||
import {IterableDiffers, KeyValueDiffers, defaultIterableDiffers, defaultKeyValueDiffers} from './change_detection/change_detection';
|
import {IterableDiffers, KeyValueDiffers, defaultIterableDiffers, defaultKeyValueDiffers} from './change_detection/change_detection';
|
||||||
|
import {ComponentFactoryResolver} from './linker/component_factory_resolver';
|
||||||
import {ComponentResolver, ReflectorComponentResolver} from './linker/component_resolver';
|
import {ComponentResolver, ReflectorComponentResolver} from './linker/component_resolver';
|
||||||
import {DynamicComponentLoader, DynamicComponentLoader_} from './linker/dynamic_component_loader';
|
import {DynamicComponentLoader, DynamicComponentLoader_} from './linker/dynamic_component_loader';
|
||||||
import {ViewUtils} from './linker/view_utils';
|
import {ViewUtils} from './linker/view_utils';
|
||||||
|
@ -26,6 +27,7 @@ export const APPLICATION_COMMON_PROVIDERS: Array<Type|{[k: string]: any}|any[]>
|
||||||
/*@ts2dart_const*/[
|
/*@ts2dart_const*/[
|
||||||
APPLICATION_CORE_PROVIDERS,
|
APPLICATION_CORE_PROVIDERS,
|
||||||
/* @ts2dart_Provider */ {provide: ComponentResolver, useClass: ReflectorComponentResolver},
|
/* @ts2dart_Provider */ {provide: ComponentResolver, useClass: ReflectorComponentResolver},
|
||||||
|
{provide: ComponentFactoryResolver, useValue: ComponentFactoryResolver.NULL},
|
||||||
APP_ID_RANDOM_PROVIDER,
|
APP_ID_RANDOM_PROVIDER,
|
||||||
ViewUtils,
|
ViewUtils,
|
||||||
/* @ts2dart_Provider */ {provide: IterableDiffers, useValue: defaultIterableDiffers},
|
/* @ts2dart_Provider */ {provide: IterableDiffers, useValue: defaultIterableDiffers},
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
// Public API for compiler
|
// Public API for compiler
|
||||||
export {ComponentFactory, ComponentRef} from './linker/component_factory';
|
export {ComponentFactory, ComponentRef} from './linker/component_factory';
|
||||||
|
export {ComponentFactoryResolver, NoComponentFactoryError} from './linker/component_factory_resolver';
|
||||||
export {ComponentResolver} from './linker/component_resolver';
|
export {ComponentResolver} from './linker/component_resolver';
|
||||||
export {DynamicComponentLoader} from './linker/dynamic_component_loader';
|
export {DynamicComponentLoader} from './linker/dynamic_component_loader';
|
||||||
export {ElementRef} from './linker/element_ref';
|
export {ElementRef} from './linker/element_ref';
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* @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 {Inject, OpaqueToken, Optional, SkipSelf} from '../di';
|
||||||
|
import {BaseException} from '../facade/exceptions';
|
||||||
|
import {ClassWithConstructor, stringify} from '../facade/lang';
|
||||||
|
|
||||||
|
import {ComponentFactory} from './component_factory';
|
||||||
|
|
||||||
|
export class NoComponentFactoryError extends BaseException {
|
||||||
|
constructor(public component: Function) {
|
||||||
|
super(`No component factory found for ${stringify(component)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NullComponentFactoryResolver implements ComponentFactoryResolver {
|
||||||
|
resolveComponentFactory<T>(component: {new (...args: any[]): T}): ComponentFactory<T> {
|
||||||
|
throw new NoComponentFactoryError(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class ComponentFactoryResolver {
|
||||||
|
static NULL: ComponentFactoryResolver = new _NullComponentFactoryResolver();
|
||||||
|
abstract resolveComponentFactory<T>(component: ClassWithConstructor<T>): ComponentFactory<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CodegenComponentFactoryResolver implements ComponentFactoryResolver {
|
||||||
|
private _factories = new Map<any, ComponentFactory<any>>();
|
||||||
|
|
||||||
|
constructor(factories: ComponentFactory<any>[], private _parent: ComponentFactoryResolver) {
|
||||||
|
for (let i = 0; i < factories.length; i++) {
|
||||||
|
let factory = factories[i];
|
||||||
|
this._factories.set(factory.componentType, factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveComponentFactory<T>(component: {new (...args: any[]): T}): ComponentFactory<T> {
|
||||||
|
let result = this._factories.get(component);
|
||||||
|
if (!result) {
|
||||||
|
result = this._parent.resolveComponentFactory(component);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -186,7 +186,8 @@ export interface ComponentMetadataFactory {
|
||||||
directives?: Array<Type|any[]>,
|
directives?: Array<Type|any[]>,
|
||||||
pipes?: Array<Type|any[]>,
|
pipes?: Array<Type|any[]>,
|
||||||
encapsulation?: ViewEncapsulation,
|
encapsulation?: ViewEncapsulation,
|
||||||
interpolation?: [string, string]
|
interpolation?: [string, string],
|
||||||
|
precompile?: Array<Type|any[]>
|
||||||
}): ComponentDecorator;
|
}): ComponentDecorator;
|
||||||
new (obj: {
|
new (obj: {
|
||||||
selector?: string,
|
selector?: string,
|
||||||
|
@ -209,7 +210,8 @@ export interface ComponentMetadataFactory {
|
||||||
directives?: Array<Type|any[]>,
|
directives?: Array<Type|any[]>,
|
||||||
pipes?: Array<Type|any[]>,
|
pipes?: Array<Type|any[]>,
|
||||||
encapsulation?: ViewEncapsulation,
|
encapsulation?: ViewEncapsulation,
|
||||||
interpolation?: [string, string]
|
interpolation?: [string, string],
|
||||||
|
precompile?: Array<Type|any[]>
|
||||||
}): ComponentMetadata;
|
}): ComponentMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -964,6 +964,14 @@ export class ComponentMetadata extends DirectiveMetadata {
|
||||||
|
|
||||||
interpolation: [string, string];
|
interpolation: [string, string];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the components that should be precompiled as well when
|
||||||
|
* this component is defined. For each components listed here,
|
||||||
|
* Angular will create a {@link ComponentFactory ComponentFactory} and store it in the
|
||||||
|
* {@link ComponentFactoryResolver ComponentFactoryResolver}.
|
||||||
|
*/
|
||||||
|
precompile: Array<Type|any[]>;
|
||||||
|
|
||||||
constructor({selector,
|
constructor({selector,
|
||||||
inputs,
|
inputs,
|
||||||
outputs,
|
outputs,
|
||||||
|
@ -984,7 +992,8 @@ export class ComponentMetadata extends DirectiveMetadata {
|
||||||
directives,
|
directives,
|
||||||
pipes,
|
pipes,
|
||||||
encapsulation,
|
encapsulation,
|
||||||
interpolation}: {
|
interpolation,
|
||||||
|
precompile}: {
|
||||||
selector?: string,
|
selector?: string,
|
||||||
inputs?: string[],
|
inputs?: string[],
|
||||||
outputs?: string[],
|
outputs?: string[],
|
||||||
|
@ -1005,7 +1014,8 @@ export class ComponentMetadata extends DirectiveMetadata {
|
||||||
directives?: Array<Type|any[]>,
|
directives?: Array<Type|any[]>,
|
||||||
pipes?: Array<Type|any[]>,
|
pipes?: Array<Type|any[]>,
|
||||||
encapsulation?: ViewEncapsulation,
|
encapsulation?: ViewEncapsulation,
|
||||||
interpolation?: [string, string]
|
interpolation?: [string, string],
|
||||||
|
precompile?: Array<Type|any[]>
|
||||||
} = {}) {
|
} = {}) {
|
||||||
super({
|
super({
|
||||||
selector: selector,
|
selector: selector,
|
||||||
|
@ -1031,6 +1041,7 @@ export class ComponentMetadata extends DirectiveMetadata {
|
||||||
this.moduleId = moduleId;
|
this.moduleId = moduleId;
|
||||||
this.animations = animations;
|
this.animations = animations;
|
||||||
this.interpolation = interpolation;
|
this.interpolation = interpolation;
|
||||||
|
this.precompile = precompile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/**
|
||||||
|
* @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 {beforeEach, ddescribe, xdescribe, describe, expect, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
|
||||||
|
import {TestComponentBuilder} from '@angular/compiler/testing';
|
||||||
|
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
|
||||||
|
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||||
|
import {Component, ViewChild, ViewContainerRef, ComponentFactoryResolver, NoComponentFactoryError, ComponentRef, forwardRef} from '@angular/core';
|
||||||
|
import {CompilerConfig} from '@angular/compiler';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('jit', () => { declareTests({useJit: true}); });
|
||||||
|
describe('no jit', () => { declareTests({useJit: false}); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function declareTests({useJit}: {useJit: boolean}) {
|
||||||
|
describe('@Component.precompile', function() {
|
||||||
|
it('should resolve ComponentFactories from the same component',
|
||||||
|
inject(
|
||||||
|
[TestComponentBuilder, AsyncTestCompleter],
|
||||||
|
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||||
|
tcb.createAsync(MainComp).then((compFixture) => {
|
||||||
|
let mainComp: MainComp = compFixture.componentInstance;
|
||||||
|
expect(compFixture.debugElement.injector.get(ComponentFactoryResolver))
|
||||||
|
.toBe(mainComp.cfr);
|
||||||
|
var cf = mainComp.cfr.resolveComponentFactory(ChildComp);
|
||||||
|
expect(cf.componentType).toBe(ChildComp);
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be able to get a component form a parent component (view hiearchy)',
|
||||||
|
inject(
|
||||||
|
[TestComponentBuilder, AsyncTestCompleter],
|
||||||
|
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||||
|
tcb.overrideTemplate(MainComp, '<child></child>')
|
||||||
|
.createAsync(MainComp)
|
||||||
|
.then((compFixture) => {
|
||||||
|
let childCompEl = compFixture.debugElement.children[0];
|
||||||
|
let childComp: ChildComp = childCompEl.componentInstance;
|
||||||
|
// declared on ChildComp directly
|
||||||
|
expect(childComp.cfr.resolveComponentFactory(NestedChildComp).componentType)
|
||||||
|
.toBe(NestedChildComp);
|
||||||
|
// inherited from MainComp
|
||||||
|
expect(childComp.cfr.resolveComponentFactory(ChildComp).componentType)
|
||||||
|
.toBe(ChildComp);
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not be able to get components from a parent component (content hierarchy)',
|
||||||
|
inject(
|
||||||
|
[TestComponentBuilder, AsyncTestCompleter],
|
||||||
|
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||||
|
tcb.overrideTemplate(MainComp, '<child><nested></nested></child>')
|
||||||
|
.overrideTemplate(ChildComp, '<ng-content></ng-content>')
|
||||||
|
.createAsync(MainComp)
|
||||||
|
.then((compFixture) => {
|
||||||
|
let nestedChildCompEl = compFixture.debugElement.children[0].children[0];
|
||||||
|
let nestedChildComp: NestedChildComp = nestedChildCompEl.componentInstance;
|
||||||
|
expect(nestedChildComp.cfr.resolveComponentFactory(ChildComp).componentType)
|
||||||
|
.toBe(ChildComp);
|
||||||
|
expect(() => nestedChildComp.cfr.resolveComponentFactory(NestedChildComp))
|
||||||
|
.toThrow(new NoComponentFactoryError(NestedChildComp));
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var DIRECTIVES: any[] = [
|
||||||
|
forwardRef(() => NestedChildComp),
|
||||||
|
forwardRef(() => ChildComp),
|
||||||
|
forwardRef(() => MainComp),
|
||||||
|
];
|
||||||
|
|
||||||
|
@Component({selector: 'nested', directives: DIRECTIVES, template: ''})
|
||||||
|
class NestedChildComp {
|
||||||
|
constructor(public cfr: ComponentFactoryResolver) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'child', precompile: [NestedChildComp], directives: DIRECTIVES, template: ''})
|
||||||
|
class ChildComp {
|
||||||
|
constructor(public cfr: ComponentFactoryResolver) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'main',
|
||||||
|
precompile: [ChildComp],
|
||||||
|
directives: DIRECTIVES,
|
||||||
|
template: '',
|
||||||
|
})
|
||||||
|
class MainComp {
|
||||||
|
constructor(public cfr: ComponentFactoryResolver) {}
|
||||||
|
}
|
|
@ -74,6 +74,8 @@ export interface Type extends Function {}
|
||||||
*/
|
*/
|
||||||
export interface ConcreteType extends Type { new (...args: any[] /** TODO #9100 */): any; }
|
export interface ConcreteType extends Type { new (...args: any[] /** TODO #9100 */): any; }
|
||||||
|
|
||||||
|
export interface ClassWithConstructor<T> { new (...args: any[]): T; }
|
||||||
|
|
||||||
export function getTypeNameForDebugging(type: Type): string {
|
export function getTypeNameForDebugging(type: Type): string {
|
||||||
if (type['name']) {
|
if (type['name']) {
|
||||||
return type['name'];
|
return type['name'];
|
||||||
|
|
|
@ -137,15 +137,19 @@ const CORE = [
|
||||||
'ComponentFactory.create(injector:Injector, projectableNodes:any[][]=null, rootSelectorOrNode:string|any=null):ComponentRef<C>',
|
'ComponentFactory.create(injector:Injector, projectableNodes:any[][]=null, rootSelectorOrNode:string|any=null):ComponentRef<C>',
|
||||||
'ComponentFactory.selector:string',
|
'ComponentFactory.selector:string',
|
||||||
'ComponentFactory<C>',
|
'ComponentFactory<C>',
|
||||||
|
'ComponentFactoryResolver',
|
||||||
|
'ComponentFactoryResolver.NULL:ComponentFactoryResolver',
|
||||||
|
'ComponentFactoryResolver.resolveComponentFactory(component:ClassWithConstructor<T>):ComponentFactory<T>',
|
||||||
'ComponentMetadata',
|
'ComponentMetadata',
|
||||||
'ComponentMetadata.animations:AnimationEntryMetadata[]',
|
'ComponentMetadata.animations:AnimationEntryMetadata[]',
|
||||||
'ComponentMetadata.changeDetection:ChangeDetectionStrategy',
|
'ComponentMetadata.changeDetection:ChangeDetectionStrategy',
|
||||||
'ComponentMetadata.constructor({selector,inputs,outputs,properties,events,host,exportAs,moduleId,providers,viewProviders,changeDetection=ChangeDetectionStrategy.Default,queries,templateUrl,template,styleUrls,styles,animations,directives,pipes,encapsulation,interpolation}:{selector?:string, inputs?:string[], outputs?:string[], properties?:string[], events?:string[], host?:{[key:string]:string}, providers?:any[], exportAs?:string, moduleId?:string, viewProviders?:any[], queries?:{[key:string]:any}, changeDetection?:ChangeDetectionStrategy, templateUrl?:string, template?:string, styleUrls?:string[], styles?:string[], animations?:AnimationEntryMetadata[], directives?:Array<Type|any[]>, pipes?:Array<Type|any[]>, encapsulation?:ViewEncapsulation, interpolation?:[string, string]}={})',
|
'ComponentMetadata.constructor({selector,inputs,outputs,properties,events,host,exportAs,moduleId,providers,viewProviders,changeDetection=ChangeDetectionStrategy.Default,queries,templateUrl,template,styleUrls,styles,animations,directives,pipes,encapsulation,interpolation,precompile}:{selector?:string, inputs?:string[], outputs?:string[], properties?:string[], events?:string[], host?:{[key:string]:string}, providers?:any[], exportAs?:string, moduleId?:string, viewProviders?:any[], queries?:{[key:string]:any}, changeDetection?:ChangeDetectionStrategy, templateUrl?:string, template?:string, styleUrls?:string[], styles?:string[], animations?:AnimationEntryMetadata[], directives?:Array<Type|any[]>, pipes?:Array<Type|any[]>, encapsulation?:ViewEncapsulation, interpolation?:[string, string], precompile?:Array<Type|any[]>}={})',
|
||||||
'ComponentMetadata.directives:Array<Type|any[]>',
|
'ComponentMetadata.directives:Array<Type|any[]>',
|
||||||
'ComponentMetadata.encapsulation:ViewEncapsulation',
|
'ComponentMetadata.encapsulation:ViewEncapsulation',
|
||||||
'ComponentMetadata.interpolation:[string, string]',
|
'ComponentMetadata.interpolation:[string, string]',
|
||||||
'ComponentMetadata.moduleId:string',
|
'ComponentMetadata.moduleId:string',
|
||||||
'ComponentMetadata.pipes:Array<Type|any[]>',
|
'ComponentMetadata.pipes:Array<Type|any[]>',
|
||||||
|
'ComponentMetadata.precompile:Array<Type|any[]>',
|
||||||
'ComponentMetadata.styles:string[]',
|
'ComponentMetadata.styles:string[]',
|
||||||
'ComponentMetadata.styleUrls:string[]',
|
'ComponentMetadata.styleUrls:string[]',
|
||||||
'ComponentMetadata.template:string',
|
'ComponentMetadata.template:string',
|
||||||
|
@ -366,6 +370,9 @@ const CORE = [
|
||||||
'NgZoneError.stackTrace:any',
|
'NgZoneError.stackTrace:any',
|
||||||
'NoAnnotationError',
|
'NoAnnotationError',
|
||||||
'NoAnnotationError.constructor(typeOrFunc:any, params:any[][])',
|
'NoAnnotationError.constructor(typeOrFunc:any, params:any[][])',
|
||||||
|
'NoComponentFactoryError',
|
||||||
|
'NoComponentFactoryError.component:Function',
|
||||||
|
'NoComponentFactoryError.constructor(component:Function)',
|
||||||
'NoProviderError',
|
'NoProviderError',
|
||||||
'NoProviderError.constructor(injector:ReflectiveInjector, key:ReflectiveKey)',
|
'NoProviderError.constructor(injector:ReflectiveInjector, key:ReflectiveKey)',
|
||||||
'OnChanges',
|
'OnChanges',
|
||||||
|
@ -1144,8 +1151,8 @@ const COMPILER = [
|
||||||
'CompileDiDependencyMetadata.viewQuery:CompileQueryMetadata',
|
'CompileDiDependencyMetadata.viewQuery:CompileQueryMetadata',
|
||||||
'CompileDirectiveMetadata',
|
'CompileDirectiveMetadata',
|
||||||
'CompileDirectiveMetadata.changeDetection:ChangeDetectionStrategy',
|
'CompileDirectiveMetadata.changeDetection:ChangeDetectionStrategy',
|
||||||
'CompileDirectiveMetadata.constructor({type,isComponent,selector,exportAs,changeDetection,inputs,outputs,hostListeners,hostProperties,hostAttributes,lifecycleHooks,providers,viewProviders,queries,viewQueries,template}:{type?:CompileTypeMetadata, isComponent?:boolean, selector?:string, exportAs?:string, changeDetection?:ChangeDetectionStrategy, inputs?:{[key:string]:string}, outputs?:{[key:string]:string}, hostListeners?:{[key:string]:string}, hostProperties?:{[key:string]:string}, hostAttributes?:{[key:string]:string}, lifecycleHooks?:LifecycleHooks[], providers?:Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, viewProviders?:Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, queries?:CompileQueryMetadata[], viewQueries?:CompileQueryMetadata[], template?:CompileTemplateMetadata}={})',
|
'CompileDirectiveMetadata.constructor({type,isComponent,selector,exportAs,changeDetection,inputs,outputs,hostListeners,hostProperties,hostAttributes,lifecycleHooks,providers,viewProviders,queries,viewQueries,precompile,template}:{type?:CompileTypeMetadata, isComponent?:boolean, selector?:string, exportAs?:string, changeDetection?:ChangeDetectionStrategy, inputs?:{[key:string]:string}, outputs?:{[key:string]:string}, hostListeners?:{[key:string]:string}, hostProperties?:{[key:string]:string}, hostAttributes?:{[key:string]:string}, lifecycleHooks?:LifecycleHooks[], providers?:Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, viewProviders?:Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, queries?:CompileQueryMetadata[], viewQueries?:CompileQueryMetadata[], precompile?:CompileTypeMetadata[], template?:CompileTemplateMetadata}={})',
|
||||||
'CompileDirectiveMetadata.create({type,isComponent,selector,exportAs,changeDetection,inputs,outputs,host,lifecycleHooks,providers,viewProviders,queries,viewQueries,template}:{type?:CompileTypeMetadata, isComponent?:boolean, selector?:string, exportAs?:string, changeDetection?:ChangeDetectionStrategy, inputs?:string[], outputs?:string[], host?:{[key:string]:string}, lifecycleHooks?:LifecycleHooks[], providers?:Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, viewProviders?:Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, queries?:CompileQueryMetadata[], viewQueries?:CompileQueryMetadata[], template?:CompileTemplateMetadata}={}):CompileDirectiveMetadata',
|
'CompileDirectiveMetadata.create({type,isComponent,selector,exportAs,changeDetection,inputs,outputs,host,lifecycleHooks,providers,viewProviders,queries,viewQueries,precompile,template}:{type?:CompileTypeMetadata, isComponent?:boolean, selector?:string, exportAs?:string, changeDetection?:ChangeDetectionStrategy, inputs?:string[], outputs?:string[], host?:{[key:string]:string}, lifecycleHooks?:LifecycleHooks[], providers?:Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, viewProviders?:Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, queries?:CompileQueryMetadata[], viewQueries?:CompileQueryMetadata[], precompile?:CompileTypeMetadata[], template?:CompileTemplateMetadata}={}):CompileDirectiveMetadata',
|
||||||
'CompileDirectiveMetadata.exportAs:string',
|
'CompileDirectiveMetadata.exportAs:string',
|
||||||
'CompileDirectiveMetadata.fromJson(data:{[key:string]:any}):CompileDirectiveMetadata',
|
'CompileDirectiveMetadata.fromJson(data:{[key:string]:any}):CompileDirectiveMetadata',
|
||||||
'CompileDirectiveMetadata.hostAttributes:{[key:string]:string}',
|
'CompileDirectiveMetadata.hostAttributes:{[key:string]:string}',
|
||||||
|
@ -1156,6 +1163,7 @@ const COMPILER = [
|
||||||
'CompileDirectiveMetadata.isComponent:boolean',
|
'CompileDirectiveMetadata.isComponent:boolean',
|
||||||
'CompileDirectiveMetadata.lifecycleHooks:LifecycleHooks[]',
|
'CompileDirectiveMetadata.lifecycleHooks:LifecycleHooks[]',
|
||||||
'CompileDirectiveMetadata.outputs:{[key:string]:string}',
|
'CompileDirectiveMetadata.outputs:{[key:string]:string}',
|
||||||
|
'CompileDirectiveMetadata.precompile:CompileTypeMetadata[]',
|
||||||
'CompileDirectiveMetadata.providers:CompileProviderMetadata[]',
|
'CompileDirectiveMetadata.providers:CompileProviderMetadata[]',
|
||||||
'CompileDirectiveMetadata.queries:CompileQueryMetadata[]',
|
'CompileDirectiveMetadata.queries:CompileQueryMetadata[]',
|
||||||
'CompileDirectiveMetadata.selector:string',
|
'CompileDirectiveMetadata.selector:string',
|
||||||
|
|
Loading…
Reference in New Issue