feat(compiler): implement style encapsulation for new view engine (#14518)
Included refactoring: - splits the `RendererV2` into a `RendererFactoryV2` and a `RendererV2` - makes the `DebugRendererV2` a private class in `@angular/core` - remove `setBindingDebugInfo` from `RendererV2`, but rename `RendererV2.setText` to `RendererV2.setValue` and allow it on comments and text nodes. Part of #14013
This commit is contained in:
parent
ba17dcbf2b
commit
0fa3895d5b
@ -101,11 +101,12 @@ export class AotCompiler {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// compile components
|
// compile components
|
||||||
|
const compViewVars = this._compileComponent(
|
||||||
|
compMeta, ngModule, ngModule.transitiveModule.directives,
|
||||||
|
stylesCompileResults.componentStylesheet, fileSuffix, statements);
|
||||||
exportedVars.push(
|
exportedVars.push(
|
||||||
this._compileComponentFactory(compMeta, ngModule, fileSuffix, statements),
|
this._compileComponentFactory(compMeta, ngModule, fileSuffix, statements),
|
||||||
this._compileComponent(
|
compViewVars.viewClassVar, compViewVars.compRenderTypeVar);
|
||||||
compMeta, ngModule, ngModule.transitiveModule.directives,
|
|
||||||
stylesCompileResults.componentStylesheet, fileSuffix, statements));
|
|
||||||
});
|
});
|
||||||
if (statements.length > 0) {
|
if (statements.length > 0) {
|
||||||
const srcModule = this._codegenSourceModule(
|
const srcModule = this._codegenSourceModule(
|
||||||
@ -175,8 +176,10 @@ export class AotCompiler {
|
|||||||
const hostType = this._metadataResolver.getHostComponentType(compMeta.type.reference);
|
const hostType = this._metadataResolver.getHostComponentType(compMeta.type.reference);
|
||||||
const hostMeta = createHostComponentMeta(
|
const hostMeta = createHostComponentMeta(
|
||||||
hostType, compMeta, this._metadataResolver.getHostComponentViewClass(hostType));
|
hostType, compMeta, this._metadataResolver.getHostComponentViewClass(hostType));
|
||||||
const hostViewFactoryVar = this._compileComponent(
|
const hostViewFactoryVar =
|
||||||
hostMeta, ngModule, [compMeta.type], null, fileSuffix, targetStatements);
|
this._compileComponent(
|
||||||
|
hostMeta, ngModule, [compMeta.type], null, fileSuffix, targetStatements)
|
||||||
|
.viewClassVar;
|
||||||
const compFactoryVar = componentFactoryName(compMeta.type.reference);
|
const compFactoryVar = componentFactoryName(compMeta.type.reference);
|
||||||
targetStatements.push(
|
targetStatements.push(
|
||||||
o.variable(compFactoryVar)
|
o.variable(compFactoryVar)
|
||||||
@ -198,7 +201,8 @@ export class AotCompiler {
|
|||||||
private _compileComponent(
|
private _compileComponent(
|
||||||
compMeta: CompileDirectiveMetadata, ngModule: CompileNgModuleMetadata,
|
compMeta: CompileDirectiveMetadata, ngModule: CompileNgModuleMetadata,
|
||||||
directiveIdentifiers: CompileIdentifierMetadata[], componentStyles: CompiledStylesheet,
|
directiveIdentifiers: CompileIdentifierMetadata[], componentStyles: CompiledStylesheet,
|
||||||
fileSuffix: string, targetStatements: o.Statement[]): string {
|
fileSuffix: string,
|
||||||
|
targetStatements: o.Statement[]): {viewClassVar: string, compRenderTypeVar: string} {
|
||||||
const parsedAnimations = this._animationParser.parseComponent(compMeta);
|
const parsedAnimations = this._animationParser.parseComponent(compMeta);
|
||||||
const directives =
|
const directives =
|
||||||
directiveIdentifiers.map(dir => this._metadataResolver.getDirectiveSummary(dir.reference));
|
directiveIdentifiers.map(dir => this._metadataResolver.getDirectiveSummary(dir.reference));
|
||||||
@ -219,7 +223,10 @@ export class AotCompiler {
|
|||||||
}
|
}
|
||||||
compiledAnimations.forEach(entry => targetStatements.push(...entry.statements));
|
compiledAnimations.forEach(entry => targetStatements.push(...entry.statements));
|
||||||
targetStatements.push(...viewResult.statements);
|
targetStatements.push(...viewResult.statements);
|
||||||
return viewResult.viewClassVar;
|
return {
|
||||||
|
viewClassVar: viewResult.viewClassVar,
|
||||||
|
compRenderTypeVar: viewResult.componentRenderTypeVar
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private _codgenStyles(
|
private _codgenStyles(
|
||||||
|
@ -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 {ChangeDetectionStrategy, ComponentFactory, SchemaMetadata, Type, ViewEncapsulation} from '@angular/core';
|
import {ChangeDetectionStrategy, ComponentFactory, ComponentRenderTypeV2, SchemaMetadata, Type, ViewEncapsulation} from '@angular/core';
|
||||||
|
|
||||||
import {StaticSymbol} from './aot/static_symbol';
|
import {StaticSymbol} from './aot/static_symbol';
|
||||||
import {ListWrapper} from './facade/collection';
|
import {ListWrapper} from './facade/collection';
|
||||||
@ -15,6 +15,7 @@ import {LifecycleHooks, reflector} from './private_import_core';
|
|||||||
import {CssSelector} from './selector';
|
import {CssSelector} from './selector';
|
||||||
import {splitAtColon} from './util';
|
import {splitAtColon} from './util';
|
||||||
|
|
||||||
|
|
||||||
// group 0: "[prop] or (event) or @trigger"
|
// group 0: "[prop] or (event) or @trigger"
|
||||||
// group 1: "prop" from "[prop]"
|
// group 1: "prop" from "[prop]"
|
||||||
// group 2: "event" from "(event)"
|
// group 2: "event" from "(event)"
|
||||||
@ -116,6 +117,10 @@ export function viewClassName(compType: any, embeddedTemplateIndex: number): str
|
|||||||
return `View_${identifierName({reference: compType})}_${embeddedTemplateIndex}`;
|
return `View_${identifierName({reference: compType})}_${embeddedTemplateIndex}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function componentRenderTypeName(compType: any): string {
|
||||||
|
return `RenderType_${identifierName({reference: compType})}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function hostViewClassName(compType: any): string {
|
export function hostViewClassName(compType: any): string {
|
||||||
return `HostView_${identifierName({reference: compType})}`;
|
return `HostView_${identifierName({reference: compType})}`;
|
||||||
}
|
}
|
||||||
@ -310,6 +315,7 @@ export interface CompileDirectiveSummary extends CompileTypeSummary {
|
|||||||
template: CompileTemplateSummary;
|
template: CompileTemplateSummary;
|
||||||
wrapperType: StaticSymbol|ProxyClass;
|
wrapperType: StaticSymbol|ProxyClass;
|
||||||
componentViewType: StaticSymbol|ProxyClass;
|
componentViewType: StaticSymbol|ProxyClass;
|
||||||
|
componentRenderType: StaticSymbol|ComponentRenderTypeV2;
|
||||||
componentFactory: StaticSymbol|ComponentFactory<any>;
|
componentFactory: StaticSymbol|ComponentFactory<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +326,7 @@ export class CompileDirectiveMetadata {
|
|||||||
static create(
|
static create(
|
||||||
{isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
|
{isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
|
||||||
providers, viewProviders, queries, viewQueries, entryComponents, template, wrapperType,
|
providers, viewProviders, queries, viewQueries, entryComponents, template, wrapperType,
|
||||||
componentViewType, componentFactory}: {
|
componentViewType, componentRenderType, componentFactory}: {
|
||||||
isHost?: boolean,
|
isHost?: boolean,
|
||||||
type?: CompileTypeMetadata,
|
type?: CompileTypeMetadata,
|
||||||
isComponent?: boolean,
|
isComponent?: boolean,
|
||||||
@ -338,6 +344,7 @@ export class CompileDirectiveMetadata {
|
|||||||
template?: CompileTemplateMetadata,
|
template?: CompileTemplateMetadata,
|
||||||
wrapperType?: StaticSymbol|ProxyClass,
|
wrapperType?: StaticSymbol|ProxyClass,
|
||||||
componentViewType?: StaticSymbol|ProxyClass,
|
componentViewType?: StaticSymbol|ProxyClass,
|
||||||
|
componentRenderType?: StaticSymbol|ComponentRenderTypeV2,
|
||||||
componentFactory?: StaticSymbol|ComponentFactory<any>,
|
componentFactory?: StaticSymbol|ComponentFactory<any>,
|
||||||
} = {}): CompileDirectiveMetadata {
|
} = {}): CompileDirectiveMetadata {
|
||||||
const hostListeners: {[key: string]: string} = {};
|
const hostListeners: {[key: string]: string} = {};
|
||||||
@ -392,6 +399,7 @@ export class CompileDirectiveMetadata {
|
|||||||
template,
|
template,
|
||||||
wrapperType,
|
wrapperType,
|
||||||
componentViewType,
|
componentViewType,
|
||||||
|
componentRenderType,
|
||||||
componentFactory,
|
componentFactory,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -416,12 +424,14 @@ export class CompileDirectiveMetadata {
|
|||||||
|
|
||||||
wrapperType: StaticSymbol|ProxyClass;
|
wrapperType: StaticSymbol|ProxyClass;
|
||||||
componentViewType: StaticSymbol|ProxyClass;
|
componentViewType: StaticSymbol|ProxyClass;
|
||||||
|
componentRenderType: StaticSymbol|ComponentRenderTypeV2;
|
||||||
componentFactory: StaticSymbol|ComponentFactory<any>;
|
componentFactory: StaticSymbol|ComponentFactory<any>;
|
||||||
|
|
||||||
constructor({isHost, type, isComponent, selector, exportAs,
|
constructor({isHost, type, isComponent, selector, exportAs,
|
||||||
changeDetection, inputs, outputs, hostListeners, hostProperties,
|
changeDetection, inputs, outputs, hostListeners, hostProperties,
|
||||||
hostAttributes, providers, viewProviders, queries, viewQueries,
|
hostAttributes, providers, viewProviders, queries, viewQueries,
|
||||||
entryComponents, template, wrapperType, componentViewType, componentFactory}: {
|
entryComponents, template, wrapperType, componentViewType, componentRenderType,
|
||||||
|
componentFactory}: {
|
||||||
isHost?: boolean,
|
isHost?: boolean,
|
||||||
type?: CompileTypeMetadata,
|
type?: CompileTypeMetadata,
|
||||||
isComponent?: boolean,
|
isComponent?: boolean,
|
||||||
@ -441,6 +451,7 @@ export class CompileDirectiveMetadata {
|
|||||||
template?: CompileTemplateMetadata,
|
template?: CompileTemplateMetadata,
|
||||||
wrapperType?: StaticSymbol|ProxyClass,
|
wrapperType?: StaticSymbol|ProxyClass,
|
||||||
componentViewType?: StaticSymbol|ProxyClass,
|
componentViewType?: StaticSymbol|ProxyClass,
|
||||||
|
componentRenderType?: StaticSymbol|ComponentRenderTypeV2,
|
||||||
componentFactory?: StaticSymbol|ComponentFactory<any>,
|
componentFactory?: StaticSymbol|ComponentFactory<any>,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
this.isHost = !!isHost;
|
this.isHost = !!isHost;
|
||||||
@ -463,6 +474,7 @@ export class CompileDirectiveMetadata {
|
|||||||
|
|
||||||
this.wrapperType = wrapperType;
|
this.wrapperType = wrapperType;
|
||||||
this.componentViewType = componentViewType;
|
this.componentViewType = componentViewType;
|
||||||
|
this.componentRenderType = componentRenderType;
|
||||||
this.componentFactory = componentFactory;
|
this.componentFactory = componentFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,6 +499,7 @@ export class CompileDirectiveMetadata {
|
|||||||
template: this.template && this.template.toSummary(),
|
template: this.template && this.template.toSummary(),
|
||||||
wrapperType: this.wrapperType,
|
wrapperType: this.wrapperType,
|
||||||
componentViewType: this.componentViewType,
|
componentViewType: this.componentViewType,
|
||||||
|
componentRenderType: this.componentRenderType,
|
||||||
componentFactory: this.componentFactory
|
componentFactory: this.componentFactory
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -521,7 +534,9 @@ export function createHostComponentMeta(
|
|||||||
viewProviders: [],
|
viewProviders: [],
|
||||||
queries: [],
|
queries: [],
|
||||||
viewQueries: [],
|
viewQueries: [],
|
||||||
componentViewType: hostViewType
|
componentViewType: hostViewType,
|
||||||
|
componentRenderType:
|
||||||
|
{id: '__Host__', encapsulation: ViewEncapsulation.None, styles: [], data: {}}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation, ɵAnimationGroupPlayer, ɵAnimationKeyframe, ɵAnimationSequencePlayer, ɵAnimationStyles, ɵAnimationTransition, ɵAppView, ɵChangeDetectorStatus, ɵCodegenComponentFactoryResolver, ɵComponentRef_, ɵDebugAppView, ɵDebugContext, ɵNgModuleInjector, ɵNoOpAnimationPlayer, ɵStaticNodeDebugInfo, ɵTemplateRef_, ɵValueUnwrapper, ɵViewContainer, ɵViewType, ɵbalanceAnimationKeyframes, ɵclearStyles, ɵcollectAndResolveStyles, ɵdevModeEqual, ɵprepareFinalAnimationStyles, ɵreflector, ɵregisterModuleFactory, ɵrenderStyles, ɵviewEngine, ɵview_utils} from '@angular/core';
|
import {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, ComponentRenderTypeV2, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation, ɵAnimationGroupPlayer, ɵAnimationKeyframe, ɵAnimationSequencePlayer, ɵAnimationStyles, ɵAnimationTransition, ɵAppView, ɵChangeDetectorStatus, ɵCodegenComponentFactoryResolver, ɵComponentRef_, ɵDebugAppView, ɵDebugContext, ɵNgModuleInjector, ɵNoOpAnimationPlayer, ɵStaticNodeDebugInfo, ɵTemplateRef_, ɵValueUnwrapper, ɵViewContainer, ɵViewType, ɵbalanceAnimationKeyframes, ɵclearStyles, ɵcollectAndResolveStyles, ɵdevModeEqual, ɵprepareFinalAnimationStyles, ɵreflector, ɵregisterModuleFactory, ɵrenderStyles, ɵviewEngine, ɵview_utils} from '@angular/core';
|
||||||
|
|
||||||
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
||||||
|
|
||||||
@ -380,6 +380,12 @@ export class Identifiers {
|
|||||||
member: 'unwrapValue',
|
member: 'unwrapValue',
|
||||||
runtime: ɵviewEngine.unwrapValue
|
runtime: ɵviewEngine.unwrapValue
|
||||||
};
|
};
|
||||||
|
static createComponentRenderTypeV2: IdentifierSpec = {
|
||||||
|
name: 'ɵviewEngine',
|
||||||
|
moduleUrl: CORE,
|
||||||
|
member: 'createComponentRenderTypeV2',
|
||||||
|
runtime: ɵviewEngine.createComponentRenderTypeV2
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assetUrl(pkg: string, path: string = null, type: string = 'src'): string {
|
export function assetUrl(pkg: string, path: string = null, type: string = 'src'): string {
|
||||||
|
@ -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 {Compiler, ComponentFactory, Inject, Injector, ModuleWithComponentFactories, NgModuleFactory, Type} from '@angular/core';
|
import {Compiler, ComponentFactory, ComponentRenderTypeV2, Inject, Injector, ModuleWithComponentFactories, NgModuleFactory, Type} from '@angular/core';
|
||||||
|
|
||||||
import {AnimationCompiler} from '../animation/animation_compiler';
|
import {AnimationCompiler} from '../animation/animation_compiler';
|
||||||
import {AnimationParser} from '../animation/animation_parser';
|
import {AnimationParser} from '../animation/animation_parser';
|
||||||
@ -133,11 +133,11 @@ export class JitCompiler implements Compiler {
|
|||||||
const compileResult = this._ngModuleCompiler.compile(moduleMeta, extraProviders);
|
const compileResult = this._ngModuleCompiler.compile(moduleMeta, extraProviders);
|
||||||
if (!this._compilerConfig.useJit) {
|
if (!this._compilerConfig.useJit) {
|
||||||
ngModuleFactory =
|
ngModuleFactory =
|
||||||
interpretStatements(compileResult.statements, compileResult.ngModuleFactoryVar);
|
interpretStatements(compileResult.statements, [compileResult.ngModuleFactoryVar])[0];
|
||||||
} else {
|
} else {
|
||||||
ngModuleFactory = jitStatements(
|
ngModuleFactory = jitStatements(
|
||||||
`/${identifierName(moduleMeta.type)}/module.ngfactory.js`, compileResult.statements,
|
`/${identifierName(moduleMeta.type)}/module.ngfactory.js`, compileResult.statements,
|
||||||
compileResult.ngModuleFactoryVar);
|
[compileResult.ngModuleFactoryVar])[0];
|
||||||
}
|
}
|
||||||
this._compiledNgModuleCache.set(moduleMeta.type.reference, ngModuleFactory);
|
this._compiledNgModuleCache.set(moduleMeta.type.reference, ngModuleFactory);
|
||||||
}
|
}
|
||||||
@ -252,11 +252,12 @@ export class JitCompiler implements Compiler {
|
|||||||
const statements = compileResult.statements;
|
const statements = compileResult.statements;
|
||||||
let directiveWrapperClass: any;
|
let directiveWrapperClass: any;
|
||||||
if (!this._compilerConfig.useJit) {
|
if (!this._compilerConfig.useJit) {
|
||||||
directiveWrapperClass = interpretStatements(statements, compileResult.dirWrapperClassVar);
|
directiveWrapperClass =
|
||||||
|
interpretStatements(statements, [compileResult.dirWrapperClassVar])[0];
|
||||||
} else {
|
} else {
|
||||||
directiveWrapperClass = jitStatements(
|
directiveWrapperClass = jitStatements(
|
||||||
`/${identifierName(moduleMeta.type)}/${identifierName(dirMeta.type)}/wrapper.ngfactory.js`,
|
`/${identifierName(moduleMeta.type)}/${identifierName(dirMeta.type)}/wrapper.ngfactory.js`,
|
||||||
statements, compileResult.dirWrapperClassVar);
|
statements, [compileResult.dirWrapperClassVar])[0];
|
||||||
}
|
}
|
||||||
(<ProxyClass>dirMeta.wrapperType).setDelegate(directiveWrapperClass);
|
(<ProxyClass>dirMeta.wrapperType).setDelegate(directiveWrapperClass);
|
||||||
this._compiledDirectiveWrapperCache.set(dirMeta.type.reference, directiveWrapperClass);
|
this._compiledDirectiveWrapperCache.set(dirMeta.type.reference, directiveWrapperClass);
|
||||||
@ -290,14 +291,18 @@ export class JitCompiler implements Compiler {
|
|||||||
.concat(...compiledAnimations.map(ca => ca.statements))
|
.concat(...compiledAnimations.map(ca => ca.statements))
|
||||||
.concat(compileResult.statements);
|
.concat(compileResult.statements);
|
||||||
let viewClass: any;
|
let viewClass: any;
|
||||||
|
let componentRenderType: any;
|
||||||
if (!this._compilerConfig.useJit) {
|
if (!this._compilerConfig.useJit) {
|
||||||
viewClass = interpretStatements(statements, compileResult.viewClassVar);
|
[viewClass, componentRenderType] = interpretStatements(
|
||||||
|
statements, [compileResult.viewClassVar, compileResult.componentRenderTypeVar]);
|
||||||
} else {
|
} else {
|
||||||
viewClass = jitStatements(
|
const sourceUrl =
|
||||||
`/${identifierName(template.ngModule.type)}/${identifierName(template.compType)}/${template.isHost?'host':'component'}.ngfactory.js`,
|
`/${identifierName(template.ngModule.type)}/${identifierName(template.compType)}/${template.isHost?'host':'component'}.ngfactory.js`;
|
||||||
statements, compileResult.viewClassVar);
|
[viewClass, componentRenderType] = jitStatements(
|
||||||
|
sourceUrl, statements,
|
||||||
|
[compileResult.viewClassVar, compileResult.componentRenderTypeVar]);
|
||||||
}
|
}
|
||||||
template.compiled(viewClass);
|
template.compiled(viewClass, componentRenderType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _resolveStylesCompileResult(
|
private _resolveStylesCompileResult(
|
||||||
@ -315,10 +320,10 @@ export class JitCompiler implements Compiler {
|
|||||||
externalStylesheetsByModuleUrl: Map<string, CompiledStylesheet>): string[] {
|
externalStylesheetsByModuleUrl: Map<string, CompiledStylesheet>): string[] {
|
||||||
this._resolveStylesCompileResult(result, externalStylesheetsByModuleUrl);
|
this._resolveStylesCompileResult(result, externalStylesheetsByModuleUrl);
|
||||||
if (!this._compilerConfig.useJit) {
|
if (!this._compilerConfig.useJit) {
|
||||||
return interpretStatements(result.statements, result.stylesVar);
|
return interpretStatements(result.statements, [result.stylesVar])[0];
|
||||||
} else {
|
} else {
|
||||||
return jitStatements(
|
return jitStatements(
|
||||||
`/${result.meta.moduleUrl}.ngstyle.js`, result.statements, result.stylesVar);
|
`/${result.meta.moduleUrl}.ngstyle.js`, result.statements, [result.stylesVar])[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,9 +337,12 @@ class CompiledTemplate {
|
|||||||
public compMeta: CompileDirectiveMetadata, public ngModule: CompileNgModuleMetadata,
|
public compMeta: CompileDirectiveMetadata, public ngModule: CompileNgModuleMetadata,
|
||||||
public directives: CompileIdentifierMetadata[]) {}
|
public directives: CompileIdentifierMetadata[]) {}
|
||||||
|
|
||||||
compiled(viewClass: Function) {
|
compiled(viewClass: Function, componentRenderType: any) {
|
||||||
this._viewClass = viewClass;
|
this._viewClass = viewClass;
|
||||||
(<ProxyClass>this.compMeta.componentViewType).setDelegate(viewClass);
|
(<ProxyClass>this.compMeta.componentViewType).setDelegate(viewClass);
|
||||||
|
for (let prop in componentRenderType) {
|
||||||
|
(<any>this.compMeta.componentRenderType)[prop] = componentRenderType[prop];
|
||||||
|
}
|
||||||
this.isCompiled = true;
|
this.isCompiled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, Attribute, ChangeDetectionStrategy, Component, ComponentFactory, Directive, Host, Inject, Injectable, InjectionToken, ModuleWithProviders, Optional, Provider, Query, SchemaMetadata, Self, SkipSelf, Type, resolveForwardRef} from '@angular/core';
|
import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, Attribute, ChangeDetectionStrategy, Component, ComponentFactory, ComponentRenderTypeV2, Directive, Host, Inject, Injectable, InjectionToken, ModuleWithProviders, Optional, Provider, Query, SchemaMetadata, Self, SkipSelf, Type, resolveForwardRef} from '@angular/core';
|
||||||
|
|
||||||
import {StaticSymbol, StaticSymbolCache} from './aot/static_symbol';
|
import {StaticSymbol, StaticSymbolCache} from './aot/static_symbol';
|
||||||
import {ngfactoryFilePath} from './aot/util';
|
import {ngfactoryFilePath} from './aot/util';
|
||||||
@ -131,6 +131,17 @@ export class CompileMetadataResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getComponentRenderType(dirType: any): StaticSymbol|ComponentRenderTypeV2 {
|
||||||
|
if (dirType instanceof StaticSymbol) {
|
||||||
|
return this._staticSymbolCache.get(
|
||||||
|
ngfactoryFilePath(dirType.filePath), cpl.componentRenderTypeName(dirType));
|
||||||
|
} else {
|
||||||
|
// returning an object as proxy,
|
||||||
|
// that we fill later during runtime compilation.
|
||||||
|
return <any>{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getComponentFactory(selector: string, dirType: any): StaticSymbol|ComponentFactory<any> {
|
private getComponentFactory(selector: string, dirType: any): StaticSymbol|ComponentFactory<any> {
|
||||||
if (dirType instanceof StaticSymbol) {
|
if (dirType instanceof StaticSymbol) {
|
||||||
return this._staticSymbolCache.get(
|
return this._staticSymbolCache.get(
|
||||||
@ -235,6 +246,7 @@ export class CompileMetadataResolver {
|
|||||||
entryComponents: metadata.entryComponents,
|
entryComponents: metadata.entryComponents,
|
||||||
wrapperType: metadata.wrapperType,
|
wrapperType: metadata.wrapperType,
|
||||||
componentViewType: metadata.componentViewType,
|
componentViewType: metadata.componentViewType,
|
||||||
|
componentRenderType: metadata.componentRenderType,
|
||||||
componentFactory: metadata.componentFactory,
|
componentFactory: metadata.componentFactory,
|
||||||
template: templateMetadata
|
template: templateMetadata
|
||||||
});
|
});
|
||||||
@ -372,6 +384,8 @@ export class CompileMetadataResolver {
|
|||||||
wrapperType: this.getDirectiveWrapperClass(directiveType),
|
wrapperType: this.getDirectiveWrapperClass(directiveType),
|
||||||
componentViewType: nonNormalizedTemplateMetadata ? this.getComponentViewClass(directiveType) :
|
componentViewType: nonNormalizedTemplateMetadata ? this.getComponentViewClass(directiveType) :
|
||||||
undefined,
|
undefined,
|
||||||
|
componentRenderType:
|
||||||
|
nonNormalizedTemplateMetadata ? this.getComponentRenderType(directiveType) : undefined,
|
||||||
componentFactory: nonNormalizedTemplateMetadata ?
|
componentFactory: nonNormalizedTemplateMetadata ?
|
||||||
this.getComponentFactory(selector, directiveType) :
|
this.getComponentFactory(selector, directiveType) :
|
||||||
undefined
|
undefined
|
||||||
|
@ -12,8 +12,9 @@ import {isPresent} from '../facade/lang';
|
|||||||
import * as o from './output_ast';
|
import * as o from './output_ast';
|
||||||
import {debugOutputAstAsTypeScript} from './ts_emitter';
|
import {debugOutputAstAsTypeScript} from './ts_emitter';
|
||||||
|
|
||||||
export function interpretStatements(statements: o.Statement[], resultVar: string): any {
|
export function interpretStatements(statements: o.Statement[], resultVars: string[]): any[] {
|
||||||
const stmtsWithReturn = statements.concat([new o.ReturnStatement(o.variable(resultVar))]);
|
const stmtsWithReturn = statements.concat(
|
||||||
|
[new o.ReturnStatement(o.literalArr(resultVars.map(resultVar => o.variable(resultVar))))]);
|
||||||
const ctx = new _ExecutionContext(null, null, null, new Map<string, any>());
|
const ctx = new _ExecutionContext(null, null, null, new Map<string, any>());
|
||||||
const visitor = new StatementInterpreter();
|
const visitor = new StatementInterpreter();
|
||||||
const result = visitor.visitAllStatements(stmtsWithReturn, ctx);
|
const result = visitor.visitAllStatements(stmtsWithReturn, ctx);
|
||||||
|
@ -13,9 +13,9 @@ import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
|
|||||||
import * as o from './output_ast';
|
import * as o from './output_ast';
|
||||||
|
|
||||||
function evalExpression(
|
function evalExpression(
|
||||||
sourceUrl: string, expr: string, ctx: EmitterVisitorContext, vars: {[key: string]: any}): any {
|
sourceUrl: string, ctx: EmitterVisitorContext, vars: {[key: string]: any}): any {
|
||||||
const fnBody =
|
const fnBody =
|
||||||
`${ctx.toSource()}\nreturn ${expr}\n//# sourceURL=${sourceUrl}\n${ctx.toSourceMapGenerator().toJsComment()}`;
|
`${ctx.toSource()}\n//# sourceURL=${sourceUrl}\n${ctx.toSourceMapGenerator().toJsComment()}`;
|
||||||
const fnArgNames: string[] = [];
|
const fnArgNames: string[] = [];
|
||||||
const fnArgValues: any[] = [];
|
const fnArgValues: any[] = [];
|
||||||
for (const argName in vars) {
|
for (const argName in vars) {
|
||||||
@ -26,11 +26,13 @@ function evalExpression(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function jitStatements(
|
export function jitStatements(
|
||||||
sourceUrl: string, statements: o.Statement[], resultVar: string): any {
|
sourceUrl: string, statements: o.Statement[], resultVars: string[]): any[] {
|
||||||
const converter = new JitEmitterVisitor();
|
const converter = new JitEmitterVisitor();
|
||||||
const ctx = EmitterVisitorContext.createRoot([resultVar]);
|
const ctx = EmitterVisitorContext.createRoot(resultVars);
|
||||||
converter.visitAllStatements(statements, ctx);
|
const returnStmt =
|
||||||
return evalExpression(sourceUrl, resultVar, ctx, converter.getArgs());
|
new o.ReturnStatement(o.literalArr(resultVars.map(resultVar => o.variable(resultVar))));
|
||||||
|
converter.visitAllStatements(statements.concat([returnStmt]), ctx);
|
||||||
|
return evalExpression(sourceUrl, ctx, converter.getArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
class JitEmitterVisitor extends AbstractJsEmitterVisitor {
|
class JitEmitterVisitor extends AbstractJsEmitterVisitor {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {AnimationEntryCompileResult} from '../animation/animation_compiler';
|
import {AnimationEntryCompileResult} from '../animation/animation_compiler';
|
||||||
import {CompileDirectiveMetadata, CompilePipeSummary, tokenName, viewClassName} from '../compile_metadata';
|
import {CompileDirectiveMetadata, CompilePipeSummary, componentRenderTypeName, tokenName, viewClassName} from '../compile_metadata';
|
||||||
import {EventHandlerVars, LegacyNameResolver} from '../compiler_util/expression_converter';
|
import {EventHandlerVars, LegacyNameResolver} from '../compiler_util/expression_converter';
|
||||||
import {CompilerConfig} from '../config';
|
import {CompilerConfig} from '../config';
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
@ -70,6 +70,7 @@ export class CompileView implements LegacyNameResolver {
|
|||||||
public pipes: CompilePipe[] = [];
|
public pipes: CompilePipe[] = [];
|
||||||
public locals = new Map<string, o.Expression>();
|
public locals = new Map<string, o.Expression>();
|
||||||
public className: string;
|
public className: string;
|
||||||
|
public renderComponentTypeName: string;
|
||||||
public classType: o.Type;
|
public classType: o.Type;
|
||||||
public classExpr: o.ReadVarExpr;
|
public classExpr: o.ReadVarExpr;
|
||||||
|
|
||||||
@ -102,6 +103,7 @@ export class CompileView implements LegacyNameResolver {
|
|||||||
|
|
||||||
this.viewType = getViewType(component, viewIndex);
|
this.viewType = getViewType(component, viewIndex);
|
||||||
this.className = viewClassName(component.type.reference, viewIndex);
|
this.className = viewClassName(component.type.reference, viewIndex);
|
||||||
|
this.renderComponentTypeName = componentRenderTypeName(component.type.reference);
|
||||||
this.classType = o.expressionType(o.variable(this.className));
|
this.classType = o.expressionType(o.variable(this.className));
|
||||||
this.classExpr = o.variable(this.className);
|
this.classExpr = o.variable(this.className);
|
||||||
if (this.viewType === ViewType.COMPONENT || this.viewType === ViewType.HOST) {
|
if (this.viewType === ViewType.COMPONENT || this.viewType === ViewType.HOST) {
|
||||||
|
@ -386,7 +386,7 @@ function createViewTopLevelStmts(view: CompileView, targetStatements: o.Statemen
|
|||||||
|
|
||||||
|
|
||||||
const renderCompTypeVar: o.ReadVarExpr =
|
const renderCompTypeVar: o.ReadVarExpr =
|
||||||
o.variable(`renderType_${identifierName(view.component.type)}`); // fix highlighting: `
|
o.variable(view.renderComponentTypeName); // fix highlighting: `
|
||||||
if (view.viewIndex === 0) {
|
if (view.viewIndex === 0) {
|
||||||
let templateUrlInfo: string;
|
let templateUrlInfo: string;
|
||||||
if (view.component.template.templateUrl == identifierModuleUrl(view.component.type)) {
|
if (view.component.template.templateUrl == identifierModuleUrl(view.component.type)) {
|
||||||
|
@ -25,6 +25,7 @@ export {ComponentFactoryDependency, ComponentViewDependency, DirectiveWrapperDep
|
|||||||
export class ViewCompileResult {
|
export class ViewCompileResult {
|
||||||
constructor(
|
constructor(
|
||||||
public statements: o.Statement[], public viewClassVar: string,
|
public statements: o.Statement[], public viewClassVar: string,
|
||||||
|
public componentRenderTypeVar: string,
|
||||||
public dependencies:
|
public dependencies:
|
||||||
Array<ComponentViewDependency|ComponentFactoryDependency|DirectiveWrapperDependency>) {}
|
Array<ComponentViewDependency|ComponentFactoryDependency|DirectiveWrapperDependency>) {}
|
||||||
}
|
}
|
||||||
@ -50,6 +51,7 @@ export class ViewCompiler {
|
|||||||
bindView(view, template, this._schemaRegistry);
|
bindView(view, template, this._schemaRegistry);
|
||||||
finishView(view, statements);
|
finishView(view, statements);
|
||||||
|
|
||||||
return new ViewCompileResult(statements, view.classExpr.name, dependencies);
|
return new ViewCompileResult(
|
||||||
|
statements, view.classExpr.name, view.renderComponentTypeName, dependencies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {ChangeDetectionStrategy} from '@angular/core';
|
import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
|
||||||
|
|
||||||
import {AnimationEntryCompileResult} from '../animation/animation_compiler';
|
import {AnimationEntryCompileResult} from '../animation/animation_compiler';
|
||||||
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileProviderMetadata, CompileTokenMetadata, CompileTypeMetadata, identifierModuleUrl, identifierName, tokenReference} from '../compile_metadata';
|
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileProviderMetadata, CompileTokenMetadata, CompileTypeMetadata, componentRenderTypeName, identifierModuleUrl, identifierName, tokenReference, viewClassName} from '../compile_metadata';
|
||||||
import {BuiltinConverter, BuiltinConverterFactory, EventHandlerVars, LocalResolver, convertActionBinding, convertPropertyBinding, convertPropertyBindingBuiltins} from '../compiler_util/expression_converter';
|
import {BuiltinConverter, BuiltinConverterFactory, EventHandlerVars, LocalResolver, convertActionBinding, convertPropertyBinding, convertPropertyBindingBuiltins} from '../compiler_util/expression_converter';
|
||||||
import {CompilerConfig} from '../config';
|
import {CompilerConfig} from '../config';
|
||||||
import {AST, ASTWithSource, Interpolation} from '../expression_parser/ast';
|
import {AST, ASTWithSource, Interpolation} from '../expression_parser/ast';
|
||||||
@ -20,7 +20,6 @@ import {convertValueToOutputAst} from '../output/value_util';
|
|||||||
import {LifecycleHooks, viewEngine} from '../private_import_core';
|
import {LifecycleHooks, viewEngine} from '../private_import_core';
|
||||||
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
||||||
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAst, ProviderAstType, QueryMatch, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast';
|
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAst, ProviderAstType, QueryMatch, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast';
|
||||||
import {ViewEncapsulationEnum} from '../view_compiler/constants';
|
|
||||||
import {ComponentFactoryDependency, ComponentViewDependency, DirectiveWrapperDependency, ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler';
|
import {ComponentFactoryDependency, ComponentViewDependency, DirectiveWrapperDependency, ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler';
|
||||||
|
|
||||||
const CLASS_ATTR = 'class';
|
const CLASS_ATTR = 'class';
|
||||||
@ -44,19 +43,33 @@ export class ViewCompilerNext extends ViewCompiler {
|
|||||||
let embeddedViewCount = 0;
|
let embeddedViewCount = 0;
|
||||||
const staticQueryIds = findStaticQueryIds(template);
|
const staticQueryIds = findStaticQueryIds(template);
|
||||||
|
|
||||||
|
const statements: o.Statement[] = [];
|
||||||
|
|
||||||
|
const renderComponentVar = o.variable(componentRenderTypeName(component.type.reference));
|
||||||
|
statements.push(
|
||||||
|
renderComponentVar
|
||||||
|
.set(o.importExpr(createIdentifier(Identifiers.createComponentRenderTypeV2)).callFn([
|
||||||
|
new o.LiteralMapExpr([
|
||||||
|
new o.LiteralMapEntry('encapsulation', o.literal(component.template.encapsulation)),
|
||||||
|
new o.LiteralMapEntry('styles', styles),
|
||||||
|
// TODO: copy this from the @Component directive...
|
||||||
|
new o.LiteralMapEntry('data', o.literalMap([])),
|
||||||
|
])
|
||||||
|
]))
|
||||||
|
.toDeclStmt());
|
||||||
|
|
||||||
const viewBuilderFactory = (parent: ViewBuilder): ViewBuilder => {
|
const viewBuilderFactory = (parent: ViewBuilder): ViewBuilder => {
|
||||||
const embeddedViewIndex = embeddedViewCount++;
|
const embeddedViewIndex = embeddedViewCount++;
|
||||||
const viewName = `view_${compName}_${embeddedViewIndex}`;
|
const viewName = viewClassName(component.type.reference, embeddedViewIndex);
|
||||||
return new ViewBuilder(parent, viewName, usedPipes, staticQueryIds, viewBuilderFactory);
|
return new ViewBuilder(parent, viewName, usedPipes, staticQueryIds, viewBuilderFactory);
|
||||||
};
|
};
|
||||||
|
|
||||||
const visitor = viewBuilderFactory(null);
|
const visitor = viewBuilderFactory(null);
|
||||||
visitor.visitAll([], template);
|
visitor.visitAll([], template);
|
||||||
|
|
||||||
const statements: o.Statement[] = [];
|
|
||||||
statements.push(...visitor.build(component));
|
statements.push(...visitor.build(component));
|
||||||
|
|
||||||
return new ViewCompileResult(statements, visitor.viewName, []);
|
return new ViewCompileResult(statements, visitor.viewName, renderComponentVar.name, []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,9 +471,11 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let compRenderType = o.NULL_EXPR;
|
||||||
let compView = o.NULL_EXPR;
|
let compView = o.NULL_EXPR;
|
||||||
if (directiveAst.directive.isComponent) {
|
if (directiveAst.directive.isComponent) {
|
||||||
compView = o.importExpr({reference: directiveAst.directive.componentViewType});
|
compView = o.importExpr({reference: directiveAst.directive.componentViewType});
|
||||||
|
compRenderType = o.importExpr({reference: directiveAst.directive.componentRenderType});
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputDefs = directiveAst.inputs.map((inputAst, inputIndex) => {
|
const inputDefs = directiveAst.inputs.map((inputAst, inputIndex) => {
|
||||||
@ -507,7 +522,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
|
|||||||
o.literal(flags), queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR,
|
o.literal(flags), queryMatchExprs.length ? o.literalArr(queryMatchExprs) : o.NULL_EXPR,
|
||||||
o.literal(childCount), providerExpr, depsExpr,
|
o.literal(childCount), providerExpr, depsExpr,
|
||||||
inputDefs.length ? new o.LiteralMapExpr(inputDefs) : o.NULL_EXPR,
|
inputDefs.length ? new o.LiteralMapExpr(inputDefs) : o.NULL_EXPR,
|
||||||
outputDefs.length ? new o.LiteralMapExpr(outputDefs) : o.NULL_EXPR, compView
|
outputDefs.length ? new o.LiteralMapExpr(outputDefs) : o.NULL_EXPR, compView, compRenderType
|
||||||
]);
|
]);
|
||||||
this.nodeDefs[nodeIndex] = nodeDef;
|
this.nodeDefs[nodeIndex] = nodeDef;
|
||||||
|
|
||||||
|
@ -93,8 +93,6 @@ export const __core_private__: {
|
|||||||
makeDecorator: typeof decorators.makeDecorator,
|
makeDecorator: typeof decorators.makeDecorator,
|
||||||
DebugDomRootRenderer: typeof debug.DebugDomRootRenderer,
|
DebugDomRootRenderer: typeof debug.DebugDomRootRenderer,
|
||||||
_DebugDomRootRenderer: debug.DebugDomRootRenderer,
|
_DebugDomRootRenderer: debug.DebugDomRootRenderer,
|
||||||
DebugDomRendererV2: typeof debug.DebugDomRendererV2,
|
|
||||||
_DebugDomRendererV2: debug.DebugDomRendererV2,
|
|
||||||
Console: typeof console.Console,
|
Console: typeof console.Console,
|
||||||
_Console: console.Console,
|
_Console: console.Console,
|
||||||
reflector: typeof reflection.reflector,
|
reflector: typeof reflection.reflector,
|
||||||
@ -158,7 +156,6 @@ export const __core_private__: {
|
|||||||
ReflectionCapabilities: reflection_capabilities.ReflectionCapabilities,
|
ReflectionCapabilities: reflection_capabilities.ReflectionCapabilities,
|
||||||
makeDecorator: decorators.makeDecorator,
|
makeDecorator: decorators.makeDecorator,
|
||||||
DebugDomRootRenderer: debug.DebugDomRootRenderer,
|
DebugDomRootRenderer: debug.DebugDomRootRenderer,
|
||||||
DebugDomRendererV2: debug.DebugDomRendererV2,
|
|
||||||
Console: console.Console,
|
Console: console.Console,
|
||||||
reflector: reflection.reflector,
|
reflector: reflection.reflector,
|
||||||
Reflector: reflection.Reflector,
|
Reflector: reflection.Reflector,
|
||||||
|
@ -10,7 +10,7 @@ import {AnimationKeyframe} from '../animation/animation_keyframe';
|
|||||||
import {AnimationPlayer} from '../animation/animation_player';
|
import {AnimationPlayer} from '../animation/animation_player';
|
||||||
import {AnimationStyles} from '../animation/animation_styles';
|
import {AnimationStyles} from '../animation/animation_styles';
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
import {RenderComponentType, RenderDebugInfo, Renderer, RendererV2, RootRenderer} from '../render/api';
|
import {RenderComponentType, RenderDebugInfo, Renderer, RootRenderer} from '../render/api';
|
||||||
|
|
||||||
import {DebugElement, DebugNode, EventListener, getDebugNode, indexDebugNode, removeDebugNodeFromIndex} from './debug_node';
|
import {DebugElement, DebugNode, EventListener, getDebugNode, indexDebugNode, removeDebugNodeFromIndex} from './debug_node';
|
||||||
|
|
||||||
@ -156,151 +156,3 @@ export class DebugDomRenderer implements Renderer {
|
|||||||
element, startingStyles, keyframes, duration, delay, easing, previousPlayers);
|
element, startingStyles, keyframes, duration, delay, easing, previousPlayers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DebugDomRendererV2 implements RendererV2 {
|
|
||||||
constructor(private _delegate: RendererV2) {}
|
|
||||||
|
|
||||||
createElement(name: string, namespace?: string, debugInfo?: any): any {
|
|
||||||
const el = this._delegate.createElement(name, namespace, debugInfo);
|
|
||||||
const debugEl = new DebugElement(el, null, debugInfo);
|
|
||||||
debugEl.name = name;
|
|
||||||
indexDebugNode(debugEl);
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
|
|
||||||
createComment(value: string, debugInfo?: any): any {
|
|
||||||
const comment = this._delegate.createComment(value, debugInfo);
|
|
||||||
const debugEl = new DebugNode(comment, null, debugInfo);
|
|
||||||
indexDebugNode(debugEl);
|
|
||||||
return comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
createText(value: string, debugInfo?: any): any {
|
|
||||||
const text = this._delegate.createText(value, debugInfo);
|
|
||||||
const debugEl = new DebugNode(text, null, debugInfo);
|
|
||||||
indexDebugNode(debugEl);
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendChild(parent: any, newChild: any): void {
|
|
||||||
const debugEl = getDebugNode(parent);
|
|
||||||
const debugChildEl = getDebugNode(newChild);
|
|
||||||
if (debugEl && debugChildEl && debugEl instanceof DebugElement) {
|
|
||||||
debugEl.addChild(debugChildEl);
|
|
||||||
}
|
|
||||||
this._delegate.appendChild(parent, newChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
insertBefore(parent: any, newChild: any, refChild: any): void {
|
|
||||||
const debugEl = getDebugNode(parent);
|
|
||||||
const debugChildEl = getDebugNode(newChild);
|
|
||||||
const debugRefEl = getDebugNode(refChild);
|
|
||||||
if (debugEl && debugChildEl && debugEl instanceof DebugElement) {
|
|
||||||
debugEl.insertBefore(debugRefEl, debugChildEl);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._delegate.insertBefore(parent, newChild, refChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeChild(parent: any, oldChild: any): void {
|
|
||||||
const debugEl = getDebugNode(parent);
|
|
||||||
const debugChildEl = getDebugNode(oldChild);
|
|
||||||
if (debugEl && debugChildEl && debugEl instanceof DebugElement) {
|
|
||||||
debugEl.removeChild(debugChildEl);
|
|
||||||
}
|
|
||||||
this._delegate.removeChild(parent, oldChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
selectRootElement(selectorOrNode: string|any, debugInfo?: any): any {
|
|
||||||
const el = this._delegate.selectRootElement(selectorOrNode, debugInfo);
|
|
||||||
const debugEl = new DebugElement(el, null, debugInfo);
|
|
||||||
indexDebugNode(debugEl);
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
|
|
||||||
parentNode(node: any): any { return this._delegate.parentNode(node); }
|
|
||||||
|
|
||||||
nextSibling(node: any): any { return this._delegate.nextSibling(node); }
|
|
||||||
|
|
||||||
setAttribute(el: any, name: string, value: string, namespace?: string): void {
|
|
||||||
const debugEl = getDebugNode(el);
|
|
||||||
if (debugEl && debugEl instanceof DebugElement) {
|
|
||||||
const fullName = namespace ? namespace + ':' + name : name;
|
|
||||||
debugEl.attributes[fullName] = value;
|
|
||||||
}
|
|
||||||
this._delegate.setAttribute(el, name, value, namespace);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeAttribute(el: any, name: string, namespace?: string): void {
|
|
||||||
const debugEl = getDebugNode(el);
|
|
||||||
if (debugEl && debugEl instanceof DebugElement) {
|
|
||||||
const fullName = namespace ? namespace + ':' + name : name;
|
|
||||||
debugEl.attributes[fullName] = null;
|
|
||||||
}
|
|
||||||
this._delegate.removeAttribute(el, name, namespace);
|
|
||||||
}
|
|
||||||
|
|
||||||
setBindingDebugInfo(el: any, propertyName: string, propertyValue: string): void {
|
|
||||||
this._delegate.setBindingDebugInfo(el, propertyName, propertyValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeBindingDebugInfo(el: any, propertyName: string): void {
|
|
||||||
this._delegate.removeBindingDebugInfo(el, propertyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
addClass(el: any, name: string): void {
|
|
||||||
const debugEl = getDebugNode(el);
|
|
||||||
if (debugEl && debugEl instanceof DebugElement) {
|
|
||||||
debugEl.classes[name] = true;
|
|
||||||
}
|
|
||||||
this._delegate.addClass(el, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeClass(el: any, name: string): void {
|
|
||||||
const debugEl = getDebugNode(el);
|
|
||||||
if (debugEl && debugEl instanceof DebugElement) {
|
|
||||||
debugEl.classes[name] = false;
|
|
||||||
}
|
|
||||||
this._delegate.removeClass(el, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
setStyle(el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean):
|
|
||||||
void {
|
|
||||||
const debugEl = getDebugNode(el);
|
|
||||||
if (debugEl && debugEl instanceof DebugElement) {
|
|
||||||
debugEl.styles[style] = value;
|
|
||||||
}
|
|
||||||
this._delegate.setStyle(el, style, value, hasVendorPrefix, hasImportant);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeStyle(el: any, style: string, hasVendorPrefix: boolean): void {
|
|
||||||
const debugEl = getDebugNode(el);
|
|
||||||
if (debugEl && debugEl instanceof DebugElement) {
|
|
||||||
debugEl.styles[style] = null;
|
|
||||||
}
|
|
||||||
this._delegate.removeStyle(el, style, hasVendorPrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
setProperty(el: any, name: string, value: any): void {
|
|
||||||
const debugEl = getDebugNode(el);
|
|
||||||
if (debugEl && debugEl instanceof DebugElement) {
|
|
||||||
debugEl.properties[name] = value;
|
|
||||||
}
|
|
||||||
this._delegate.setProperty(el, name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
setText(node: any, value: string): void { this._delegate.setText(node, value); }
|
|
||||||
|
|
||||||
listen(
|
|
||||||
target: 'document'|'windows'|'body'|any, eventName: string,
|
|
||||||
callback: (event: any) => boolean): () => void {
|
|
||||||
if (typeof target !== 'string') {
|
|
||||||
const debugEl = getDebugNode(target);
|
|
||||||
if (debugEl) {
|
|
||||||
debugEl.listeners.push(new EventListener(eventName, callback));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._delegate.listen(target, eventName, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -7,4 +7,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Public API for render
|
// Public API for render
|
||||||
export {RENDERER_V2_DIRECT, RenderComponentType, Renderer, RendererV2, RootRenderer} from './render/api';
|
export {ComponentRenderTypeV2, RenderComponentType, Renderer, RendererFactoryV2, RendererV2, RootRenderer} from './render/api';
|
||||||
|
@ -12,13 +12,6 @@ import {AnimationStyles} from '../../src/animation/animation_styles';
|
|||||||
import {InjectionToken, Injector} from '../di';
|
import {InjectionToken, Injector} from '../di';
|
||||||
import {ViewEncapsulation} from '../metadata/view';
|
import {ViewEncapsulation} from '../metadata/view';
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide a concrete implementation of {@link RendererV2}
|
|
||||||
*
|
|
||||||
* @experimental
|
|
||||||
*/
|
|
||||||
export const RENDERER_V2_DIRECT = new InjectionToken<RendererV2>('Renderer V2');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
@ -98,56 +91,6 @@ export abstract class Renderer {
|
|||||||
previousPlayers?: AnimationPlayer[]): AnimationPlayer;
|
previousPlayers?: AnimationPlayer[]): AnimationPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @experimental
|
|
||||||
*/
|
|
||||||
export abstract class RendererV2 {
|
|
||||||
abstract createElement(name: string, namespace?: string, debugInfo?: RenderDebugContext): any;
|
|
||||||
abstract createComment(value: string, debugInfo?: RenderDebugContext): any;
|
|
||||||
abstract createText(value: string, debugInfo?: RenderDebugContext): any;
|
|
||||||
abstract appendChild(parent: any, newChild: any): void;
|
|
||||||
abstract insertBefore(parent: any, newChild: any, refChild: any): void;
|
|
||||||
abstract removeChild(parent: any, oldChild: any): void;
|
|
||||||
abstract selectRootElement(selectorOrNode: string|any, debugInfo?: RenderDebugContext): any;
|
|
||||||
/**
|
|
||||||
* Attention: On WebWorkers, this will always return a value,
|
|
||||||
* as we are asking for a result synchronously. I.e.
|
|
||||||
* the caller can't rely on checking whether this is null or not.
|
|
||||||
*/
|
|
||||||
abstract parentNode(node: any): any;
|
|
||||||
/**
|
|
||||||
* Attention: On WebWorkers, this will always return a value,
|
|
||||||
* as we are asking for a result synchronously. I.e.
|
|
||||||
* the caller can't rely on checking whether this is null or not.
|
|
||||||
*/
|
|
||||||
abstract nextSibling(node: any): any;
|
|
||||||
abstract setAttribute(el: any, name: string, value: string, namespace?: string): void;
|
|
||||||
abstract removeAttribute(el: any, name: string, namespace?: string): void;
|
|
||||||
abstract setBindingDebugInfo(el: any, propertyName: string, propertyValue: string): void;
|
|
||||||
abstract removeBindingDebugInfo(el: any, propertyName: string): void;
|
|
||||||
abstract addClass(el: any, name: string): void;
|
|
||||||
abstract removeClass(el: any, name: string): void;
|
|
||||||
abstract setStyle(
|
|
||||||
el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean): void;
|
|
||||||
abstract removeStyle(el: any, style: string, hasVendorPrefix: boolean): void;
|
|
||||||
abstract setProperty(el: any, name: string, value: any): void;
|
|
||||||
abstract setText(node: any, value: string): void;
|
|
||||||
abstract listen(
|
|
||||||
target: 'window'|'document'|'body'|any, eventName: string,
|
|
||||||
callback: (event: any) => boolean): () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class RenderDebugContext {
|
|
||||||
abstract get injector(): Injector;
|
|
||||||
abstract get component(): any;
|
|
||||||
abstract get providerTokens(): any[];
|
|
||||||
abstract get references(): {[key: string]: any};
|
|
||||||
abstract get context(): any;
|
|
||||||
abstract get source(): string;
|
|
||||||
abstract get componentRenderElement(): any;
|
|
||||||
abstract get renderNode(): any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injectable service that provides a low-level interface for modifying the UI.
|
* Injectable service that provides a low-level interface for modifying the UI.
|
||||||
*
|
*
|
||||||
@ -164,3 +107,64 @@ export abstract class RenderDebugContext {
|
|||||||
export abstract class RootRenderer {
|
export abstract class RootRenderer {
|
||||||
abstract renderComponent(componentType: RenderComponentType): Renderer;
|
abstract renderComponent(componentType: RenderComponentType): Renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
export interface ComponentRenderTypeV2 {
|
||||||
|
id: string;
|
||||||
|
encapsulation: ViewEncapsulation;
|
||||||
|
styles: (string|any[])[];
|
||||||
|
data: {[kind: string]: any[]};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
export abstract class RendererFactoryV2 {
|
||||||
|
abstract createRenderer(hostElement: any, type: ComponentRenderTypeV2): RendererV2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
export abstract class RendererV2 {
|
||||||
|
abstract destroy(): void;
|
||||||
|
abstract createElement(name: string, namespace?: string): any;
|
||||||
|
abstract createComment(value: string): any;
|
||||||
|
abstract createText(value: string): any;
|
||||||
|
/**
|
||||||
|
* This property is allowed to be null / undefined,
|
||||||
|
* in which case the view engine won't call it.
|
||||||
|
* This is used as a performance optimization for production mode.
|
||||||
|
*/
|
||||||
|
destroyNode: (node: any) => void | null;
|
||||||
|
abstract appendChild(parent: any, newChild: any): void;
|
||||||
|
abstract insertBefore(parent: any, newChild: any, refChild: any): void;
|
||||||
|
abstract removeChild(parent: any, oldChild: any): void;
|
||||||
|
abstract selectRootElement(selectorOrNode: string|any): any;
|
||||||
|
/**
|
||||||
|
* Attention: On WebWorkers, this will always return a value,
|
||||||
|
* as we are asking for a result synchronously. I.e.
|
||||||
|
* the caller can't rely on checking whether this is null or not.
|
||||||
|
*/
|
||||||
|
abstract parentNode(node: any): any;
|
||||||
|
/**
|
||||||
|
* Attention: On WebWorkers, this will always return a value,
|
||||||
|
* as we are asking for a result synchronously. I.e.
|
||||||
|
* the caller can't rely on checking whether this is null or not.
|
||||||
|
*/
|
||||||
|
abstract nextSibling(node: any): any;
|
||||||
|
abstract setAttribute(el: any, name: string, value: string, namespace?: string): void;
|
||||||
|
abstract removeAttribute(el: any, name: string, namespace?: string): void;
|
||||||
|
abstract addClass(el: any, name: string): void;
|
||||||
|
abstract removeClass(el: any, name: string): void;
|
||||||
|
abstract setStyle(
|
||||||
|
el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean): void;
|
||||||
|
abstract removeStyle(el: any, style: string, hasVendorPrefix: boolean): void;
|
||||||
|
abstract setProperty(el: any, name: string, value: any): void;
|
||||||
|
abstract setValue(node: any, value: string): void;
|
||||||
|
abstract listen(
|
||||||
|
target: 'window'|'document'|'body'|any, eventName: string,
|
||||||
|
callback: (event: any) => boolean): () => void;
|
||||||
|
}
|
||||||
|
@ -132,7 +132,7 @@ export function elementDef(
|
|||||||
export function createElement(view: ViewData, renderHost: any, def: NodeDef): ElementData {
|
export function createElement(view: ViewData, renderHost: any, def: NodeDef): ElementData {
|
||||||
const elDef = def.element;
|
const elDef = def.element;
|
||||||
const rootSelectorOrNode = view.root.selectorOrNode;
|
const rootSelectorOrNode = view.root.selectorOrNode;
|
||||||
const renderer = view.root.renderer;
|
const renderer = view.renderer;
|
||||||
let el: any;
|
let el: any;
|
||||||
if (view.parent || !rootSelectorOrNode) {
|
if (view.parent || !rootSelectorOrNode) {
|
||||||
if (elDef.name) {
|
if (elDef.name) {
|
||||||
@ -240,7 +240,7 @@ function setElementAttribute(
|
|||||||
const securityContext = binding.securityContext;
|
const securityContext = binding.securityContext;
|
||||||
let renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
|
let renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
|
||||||
renderValue = renderValue != null ? renderValue.toString() : null;
|
renderValue = renderValue != null ? renderValue.toString() : null;
|
||||||
const renderer = view.root.renderer;
|
const renderer = view.renderer;
|
||||||
// TODO(vicb): move the namespace to the node definition
|
// TODO(vicb): move the namespace to the node definition
|
||||||
const nsAndName = splitNamespace(name);
|
const nsAndName = splitNamespace(name);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@ -251,7 +251,7 @@ function setElementAttribute(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setElementClass(view: ViewData, renderNode: any, name: string, value: boolean) {
|
function setElementClass(view: ViewData, renderNode: any, name: string, value: boolean) {
|
||||||
const renderer = view.root.renderer;
|
const renderer = view.renderer;
|
||||||
if (value) {
|
if (value) {
|
||||||
renderer.addClass(renderNode, name);
|
renderer.addClass(renderNode, name);
|
||||||
} else {
|
} else {
|
||||||
@ -271,7 +271,7 @@ function setElementStyle(
|
|||||||
} else {
|
} else {
|
||||||
renderValue = null;
|
renderValue = null;
|
||||||
}
|
}
|
||||||
const renderer = view.root.renderer;
|
const renderer = view.renderer;
|
||||||
if (renderValue != null) {
|
if (renderValue != null) {
|
||||||
renderer.setStyle(renderNode, name, renderValue, false, false);
|
renderer.setStyle(renderNode, name, renderValue, false, false);
|
||||||
} else {
|
} else {
|
||||||
@ -283,7 +283,7 @@ function setElementProperty(
|
|||||||
view: ViewData, binding: BindingDef, renderNode: any, name: string, value: any) {
|
view: ViewData, binding: BindingDef, renderNode: any, name: string, value: any) {
|
||||||
const securityContext = binding.securityContext;
|
const securityContext = binding.securityContext;
|
||||||
let renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
|
let renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
|
||||||
view.root.renderer.setProperty(renderNode, name, renderValue);
|
view.renderer.setProperty(renderNode, name, renderValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NS_PREFIX_RE = /^:([^:]+):(.+)$/;
|
const NS_PREFIX_RE = /^:([^:]+):(.+)$/;
|
||||||
|
@ -14,7 +14,7 @@ export {queryDef} from './query';
|
|||||||
export {createComponentFactory} from './refs';
|
export {createComponentFactory} from './refs';
|
||||||
export {initServicesIfNeeded} from './services';
|
export {initServicesIfNeeded} from './services';
|
||||||
export {textDef} from './text';
|
export {textDef} from './text';
|
||||||
export {elementEventFullName, nodeValue, rootRenderNodes, unwrapValue} from './util';
|
export {createComponentRenderTypeV2, elementEventFullName, nodeValue, rootRenderNodes, unwrapValue} from './util';
|
||||||
export {viewDef} from './view';
|
export {viewDef} from './view';
|
||||||
export {attachEmbeddedView, detachEmbeddedView, moveEmbeddedView} from './view_attach';
|
export {attachEmbeddedView, detachEmbeddedView, moveEmbeddedView} from './view_attach';
|
||||||
|
|
||||||
|
@ -11,13 +11,15 @@ import {Injector} from '../di';
|
|||||||
import {ElementRef} from '../linker/element_ref';
|
import {ElementRef} from '../linker/element_ref';
|
||||||
import {TemplateRef} from '../linker/template_ref';
|
import {TemplateRef} from '../linker/template_ref';
|
||||||
import {ViewContainerRef} from '../linker/view_container_ref';
|
import {ViewContainerRef} from '../linker/view_container_ref';
|
||||||
import * as v1renderer from '../render/api';
|
import {ViewEncapsulation} from '../metadata/view';
|
||||||
|
import {ComponentRenderTypeV2, RenderComponentType as RenderComponentTypeV1, Renderer as RendererV1, RendererFactoryV2, RendererV2, RootRenderer as RootRendererV1} from '../render/api';
|
||||||
|
|
||||||
import {createChangeDetectorRef, createInjector, createTemplateRef, createViewContainerRef} from './refs';
|
import {createChangeDetectorRef, createInjector, createTemplateRef, createViewContainerRef} from './refs';
|
||||||
import {BindingDef, BindingType, DepDef, DepFlags, DirectiveOutputDef, DisposableFn, NodeData, NodeDef, NodeFlags, NodeType, ProviderData, ProviderType, QueryBindingType, QueryDef, QueryValueType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewState, asElementData, asProviderData} from './types';
|
import {BindingDef, BindingType, DepDef, DepFlags, DirectiveOutputDef, DisposableFn, NodeData, NodeDef, NodeFlags, NodeType, ProviderData, ProviderType, QueryBindingType, QueryDef, QueryValueType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewState, asElementData, asProviderData} from './types';
|
||||||
import {checkAndUpdateBinding, dispatchEvent, filterQueryId, isComponentView, splitMatchedQueriesDsl, tokenKey, viewParentEl} from './util';
|
import {checkAndUpdateBinding, dispatchEvent, filterQueryId, isComponentView, splitMatchedQueriesDsl, tokenKey, viewParentEl} from './util';
|
||||||
|
|
||||||
const RendererV1TokenKey = tokenKey(v1renderer.Renderer);
|
const RendererV1TokenKey = tokenKey(RendererV1);
|
||||||
|
const RendererV2TokenKey = tokenKey(RendererV2);
|
||||||
const ElementRefTokenKey = tokenKey(ElementRef);
|
const ElementRefTokenKey = tokenKey(ElementRef);
|
||||||
const ViewContainerRefTokenKey = tokenKey(ViewContainerRef);
|
const ViewContainerRefTokenKey = tokenKey(ViewContainerRef);
|
||||||
const TemplateRefTokenKey = tokenKey(TemplateRef);
|
const TemplateRefTokenKey = tokenKey(TemplateRef);
|
||||||
@ -29,7 +31,8 @@ const NOT_CREATED = new Object();
|
|||||||
export function directiveDef(
|
export function directiveDef(
|
||||||
flags: NodeFlags, matchedQueries: [string | number, QueryValueType][], childCount: number,
|
flags: NodeFlags, matchedQueries: [string | number, QueryValueType][], childCount: number,
|
||||||
ctor: any, deps: ([DepFlags, any] | any)[], props?: {[name: string]: [number, string]},
|
ctor: any, deps: ([DepFlags, any] | any)[], props?: {[name: string]: [number, string]},
|
||||||
outputs?: {[name: string]: string}, component?: () => ViewDefinition): NodeDef {
|
outputs?: {[name: string]: string}, component?: () => ViewDefinition,
|
||||||
|
componentRenderType?: ComponentRenderTypeV2): NodeDef {
|
||||||
const bindings: BindingDef[] = [];
|
const bindings: BindingDef[] = [];
|
||||||
if (props) {
|
if (props) {
|
||||||
for (let prop in props) {
|
for (let prop in props) {
|
||||||
@ -50,7 +53,7 @@ export function directiveDef(
|
|||||||
}
|
}
|
||||||
return _def(
|
return _def(
|
||||||
NodeType.Directive, flags, matchedQueries, childCount, ProviderType.Class, ctor, ctor, deps,
|
NodeType.Directive, flags, matchedQueries, childCount, ProviderType.Class, ctor, ctor, deps,
|
||||||
bindings, outputDefs, component);
|
bindings, outputDefs, component, componentRenderType);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pipeDef(flags: NodeFlags, ctor: any, deps: ([DepFlags, any] | any)[]): NodeDef {
|
export function pipeDef(flags: NodeFlags, ctor: any, deps: ([DepFlags, any] | any)[]): NodeDef {
|
||||||
@ -67,8 +70,13 @@ export function _def(
|
|||||||
type: NodeType, flags: NodeFlags, matchedQueriesDsl: [string | number, QueryValueType][],
|
type: NodeType, flags: NodeFlags, matchedQueriesDsl: [string | number, QueryValueType][],
|
||||||
childCount: number, providerType: ProviderType, token: any, value: any,
|
childCount: number, providerType: ProviderType, token: any, value: any,
|
||||||
deps: ([DepFlags, any] | any)[], bindings?: BindingDef[], outputs?: DirectiveOutputDef[],
|
deps: ([DepFlags, any] | any)[], bindings?: BindingDef[], outputs?: DirectiveOutputDef[],
|
||||||
component?: () => ViewDefinition): NodeDef {
|
component?: () => ViewDefinition, componentRenderType?: ComponentRenderTypeV2): NodeDef {
|
||||||
const {matchedQueries, references, matchedQueryIds} = splitMatchedQueriesDsl(matchedQueriesDsl);
|
const {matchedQueries, references, matchedQueryIds} = splitMatchedQueriesDsl(matchedQueriesDsl);
|
||||||
|
// This is needed as the jit compiler always uses an empty hash as default ComponentRenderTypeV2,
|
||||||
|
// which is not filled for host views.
|
||||||
|
if (componentRenderType && componentRenderType.encapsulation == null) {
|
||||||
|
componentRenderType = null;
|
||||||
|
}
|
||||||
if (!outputs) {
|
if (!outputs) {
|
||||||
outputs = [];
|
outputs = [];
|
||||||
}
|
}
|
||||||
@ -111,7 +119,7 @@ export function _def(
|
|||||||
type: providerType,
|
type: providerType,
|
||||||
token,
|
token,
|
||||||
tokenKey: tokenKey(token), value,
|
tokenKey: tokenKey(token), value,
|
||||||
deps: depDefs, outputs, component
|
deps: depDefs, outputs, component, componentRenderType
|
||||||
},
|
},
|
||||||
text: undefined,
|
text: undefined,
|
||||||
pureExpression: undefined,
|
pureExpression: undefined,
|
||||||
@ -328,16 +336,19 @@ export function resolveDep(
|
|||||||
if (elDef) {
|
if (elDef) {
|
||||||
switch (tokenKey) {
|
switch (tokenKey) {
|
||||||
case RendererV1TokenKey: {
|
case RendererV1TokenKey: {
|
||||||
let compView = view;
|
const compView = findCompView(view, elDef, allowPrivateServices);
|
||||||
while (compView && !isComponentView(compView)) {
|
const compDef = compView.parentNodeDef;
|
||||||
compView = compView.parent;
|
const rootRendererV1: RootRendererV1 = view.root.injector.get(RootRendererV1);
|
||||||
}
|
|
||||||
const rootRenderer: v1renderer.RootRenderer =
|
|
||||||
view.root.injector.get(v1renderer.RootRenderer);
|
|
||||||
|
|
||||||
// Note: Don't fill in the styles as they have been installed already!
|
// Note: Don't fill in the styles as they have been installed already via the RendererV2!
|
||||||
return rootRenderer.renderComponent(new v1renderer.RenderComponentType(
|
const compRenderType = compDef.provider.componentRenderType;
|
||||||
view.def.component.id, '', 0, view.def.component.encapsulation, [], {}));
|
return rootRendererV1.renderComponent(new RenderComponentTypeV1(
|
||||||
|
compRenderType ? compRenderType.id : '0', '', 0,
|
||||||
|
compRenderType ? compRenderType.encapsulation : ViewEncapsulation.None, [], {}));
|
||||||
|
}
|
||||||
|
case RendererV2TokenKey: {
|
||||||
|
const compView = findCompView(view, elDef, allowPrivateServices);
|
||||||
|
return compView.renderer;
|
||||||
}
|
}
|
||||||
case ElementRefTokenKey:
|
case ElementRefTokenKey:
|
||||||
return new ElementRef(asElementData(view, elDef.index).renderElement);
|
return new ElementRef(asElementData(view, elDef.index).renderElement);
|
||||||
@ -350,15 +361,7 @@ export function resolveDep(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ChangeDetectorRefTokenKey: {
|
case ChangeDetectorRefTokenKey: {
|
||||||
let cdView: ViewData;
|
let cdView = findCompView(view, elDef, allowPrivateServices);
|
||||||
if (allowPrivateServices) {
|
|
||||||
cdView = asProviderData(view, elDef.element.component.index).componentView;
|
|
||||||
} else {
|
|
||||||
cdView = view;
|
|
||||||
while (cdView.parent && !isComponentView(cdView)) {
|
|
||||||
cdView = cdView.parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return createChangeDetectorRef(cdView);
|
return createChangeDetectorRef(cdView);
|
||||||
}
|
}
|
||||||
case InjectorRefTokenKey:
|
case InjectorRefTokenKey:
|
||||||
@ -383,6 +386,19 @@ export function resolveDep(
|
|||||||
return startView.root.injector.get(depDef.token, notFoundValue);
|
return startView.root.injector.get(depDef.token, notFoundValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findCompView(view: ViewData, elDef: NodeDef, allowPrivateServices: boolean) {
|
||||||
|
let compView: ViewData;
|
||||||
|
if (allowPrivateServices) {
|
||||||
|
compView = asProviderData(view, elDef.element.component.index).componentView;
|
||||||
|
} else {
|
||||||
|
compView = view;
|
||||||
|
while (compView.parent && !isComponentView(compView)) {
|
||||||
|
compView = compView.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return compView;
|
||||||
|
}
|
||||||
|
|
||||||
function checkAndUpdateProp(
|
function checkAndUpdateProp(
|
||||||
view: ViewData, providerData: ProviderData, def: NodeDef, bindingIdx: number, value: any,
|
view: ViewData, providerData: ProviderData, def: NodeDef, bindingIdx: number, value: any,
|
||||||
changes: SimpleChanges): SimpleChanges {
|
changes: SimpleChanges): SimpleChanges {
|
||||||
|
@ -201,8 +201,9 @@ export function createInjector(view: ViewData, elDef: NodeDef): Injector {
|
|||||||
class Injector_ implements Injector {
|
class Injector_ implements Injector {
|
||||||
constructor(private view: ViewData, private elDef: NodeDef) {}
|
constructor(private view: ViewData, private elDef: NodeDef) {}
|
||||||
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
|
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
|
||||||
|
const allowPrivateServices = !!this.elDef.element.component;
|
||||||
return Services.resolveDep(
|
return Services.resolveDep(
|
||||||
this.view, this.elDef, true, {flags: DepFlags.None, token, tokenKey: tokenKey(token)},
|
this.view, this.elDef, allowPrivateServices,
|
||||||
notFoundValue);
|
{flags: DepFlags.None, token, tokenKey: tokenKey(token)}, notFoundValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {isDevMode} from '../application_ref';
|
import {isDevMode} from '../application_ref';
|
||||||
|
import {DebugElement, DebugNode, EventListener, getDebugNode, indexDebugNode, removeDebugNodeFromIndex} from '../debug/debug_node';
|
||||||
import {Injector} from '../di';
|
import {Injector} from '../di';
|
||||||
import {RendererV2} from '../render/api';
|
import {ComponentRenderTypeV2, RendererFactoryV2, RendererV2} from '../render/api';
|
||||||
import {Sanitizer, SecurityContext} from '../security';
|
import {Sanitizer, SecurityContext} from '../security';
|
||||||
|
|
||||||
import {isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors';
|
import {isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors';
|
||||||
@ -87,52 +88,59 @@ function createDebugServices() {
|
|||||||
function createProdRootView(
|
function createProdRootView(
|
||||||
injector: Injector, projectableNodes: any[][], rootSelectorOrNode: string | any,
|
injector: Injector, projectableNodes: any[][], rootSelectorOrNode: string | any,
|
||||||
def: ViewDefinition, context?: any): ViewData {
|
def: ViewDefinition, context?: any): ViewData {
|
||||||
|
const rendererFactory: RendererFactoryV2 = injector.get(RendererFactoryV2);
|
||||||
return createRootView(
|
return createRootView(
|
||||||
createRootData(injector, projectableNodes, rootSelectorOrNode), def, context);
|
createRootData(injector, rendererFactory, projectableNodes, rootSelectorOrNode), def,
|
||||||
|
context);
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugCreateRootView(
|
function debugCreateRootView(
|
||||||
injector: Injector, projectableNodes: any[][], rootSelectorOrNode: string | any,
|
injector: Injector, projectableNodes: any[][], rootSelectorOrNode: string | any,
|
||||||
def: ViewDefinition, context?: any): ViewData {
|
def: ViewDefinition, context?: any): ViewData {
|
||||||
const root = createRootData(injector, projectableNodes, rootSelectorOrNode);
|
const rendererFactory: RendererFactoryV2 = injector.get(RendererFactoryV2);
|
||||||
const debugRoot: RootData = {
|
const root = createRootData(
|
||||||
injector: root.injector,
|
injector, new DebugRendererFactoryV2(rendererFactory), projectableNodes, rootSelectorOrNode);
|
||||||
projectableNodes: root.projectableNodes,
|
return callWithDebugContext(DebugAction.create, createRootView, null, [root, def, context]);
|
||||||
selectorOrNode: root.selectorOrNode,
|
|
||||||
renderer: new DebugRenderer(root.renderer),
|
|
||||||
sanitizer: root.sanitizer
|
|
||||||
};
|
|
||||||
return callWithDebugContext('create', createRootView, null, [debugRoot, def, context]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createRootData(
|
function createRootData(
|
||||||
injector: Injector, projectableNodes: any[][], rootSelectorOrNode: any): RootData {
|
injector: Injector, rendererFactory: RendererFactoryV2, projectableNodes: any[][],
|
||||||
|
rootSelectorOrNode: any): RootData {
|
||||||
const sanitizer = injector.get(Sanitizer);
|
const sanitizer = injector.get(Sanitizer);
|
||||||
const renderer = injector.get(RendererV2);
|
const renderer = rendererFactory.createRenderer(null, null);
|
||||||
|
return {
|
||||||
const rootElement =
|
injector,
|
||||||
rootSelectorOrNode ? renderer.selectRootElement(rootSelectorOrNode) : undefined;
|
projectableNodes,
|
||||||
return {injector, projectableNodes, selectorOrNode: rootSelectorOrNode, sanitizer, renderer};
|
selectorOrNode: rootSelectorOrNode, sanitizer, rendererFactory, renderer
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugCreateEmbeddedView(parent: ViewData, anchorDef: NodeDef, context?: any): ViewData {
|
function debugCreateEmbeddedView(parent: ViewData, anchorDef: NodeDef, context?: any): ViewData {
|
||||||
return callWithDebugContext('create', createEmbeddedView, null, [parent, anchorDef, context]);
|
return callWithDebugContext(
|
||||||
|
DebugAction.create, createEmbeddedView, null, [parent, anchorDef, context]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugCheckAndUpdateView(view: ViewData) {
|
function debugCheckAndUpdateView(view: ViewData) {
|
||||||
return callWithDebugContext('detectChanges', checkAndUpdateView, null, [view]);
|
return callWithDebugContext(DebugAction.detectChanges, checkAndUpdateView, null, [view]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugCheckNoChangesView(view: ViewData) {
|
function debugCheckNoChangesView(view: ViewData) {
|
||||||
return callWithDebugContext('checkNoChanges', checkNoChangesView, null, [view]);
|
return callWithDebugContext(DebugAction.checkNoChanges, checkNoChangesView, null, [view]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugDestroyView(view: ViewData) {
|
function debugDestroyView(view: ViewData) {
|
||||||
return callWithDebugContext('destroyView', destroyView, null, [view]);
|
return callWithDebugContext(DebugAction.destroy, destroyView, null, [view]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DebugAction {
|
||||||
|
create,
|
||||||
|
detectChanges,
|
||||||
|
checkNoChanges,
|
||||||
|
destroy,
|
||||||
|
handleEvent
|
||||||
|
}
|
||||||
|
|
||||||
let _currentAction: string;
|
let _currentAction: DebugAction;
|
||||||
let _currentView: ViewData;
|
let _currentView: ViewData;
|
||||||
let _currentNodeIndex: number;
|
let _currentNodeIndex: number;
|
||||||
|
|
||||||
@ -143,16 +151,16 @@ function debugSetCurrentNode(view: ViewData, nodeIndex: number) {
|
|||||||
|
|
||||||
function debugHandleEvent(view: ViewData, nodeIndex: number, eventName: string, event: any) {
|
function debugHandleEvent(view: ViewData, nodeIndex: number, eventName: string, event: any) {
|
||||||
if (view.state & ViewState.Destroyed) {
|
if (view.state & ViewState.Destroyed) {
|
||||||
throw viewDestroyedError(_currentAction);
|
throw viewDestroyedError(DebugAction[_currentAction]);
|
||||||
}
|
}
|
||||||
debugSetCurrentNode(view, nodeIndex);
|
debugSetCurrentNode(view, nodeIndex);
|
||||||
return callWithDebugContext(
|
return callWithDebugContext(
|
||||||
'handleEvent', view.def.handleEvent, null, [view, nodeIndex, eventName, event]);
|
DebugAction.handleEvent, view.def.handleEvent, null, [view, nodeIndex, eventName, event]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugUpdateDirectives(check: NodeCheckFn, view: ViewData) {
|
function debugUpdateDirectives(check: NodeCheckFn, view: ViewData) {
|
||||||
if (view.state & ViewState.Destroyed) {
|
if (view.state & ViewState.Destroyed) {
|
||||||
throw viewDestroyedError(_currentAction);
|
throw viewDestroyedError(DebugAction[_currentAction]);
|
||||||
}
|
}
|
||||||
debugSetCurrentNode(view, nextDirectiveWithBinding(view, 0));
|
debugSetCurrentNode(view, nextDirectiveWithBinding(view, 0));
|
||||||
return view.def.updateDirectives(debugCheckDirectivesFn, view);
|
return view.def.updateDirectives(debugCheckDirectivesFn, view);
|
||||||
@ -167,7 +175,7 @@ function debugUpdateDirectives(check: NodeCheckFn, view: ViewData) {
|
|||||||
|
|
||||||
function debugUpdateRenderer(check: NodeCheckFn, view: ViewData) {
|
function debugUpdateRenderer(check: NodeCheckFn, view: ViewData) {
|
||||||
if (view.state & ViewState.Destroyed) {
|
if (view.state & ViewState.Destroyed) {
|
||||||
throw viewDestroyedError(_currentAction);
|
throw viewDestroyedError(DebugAction[_currentAction]);
|
||||||
}
|
}
|
||||||
debugSetCurrentNode(view, nextRenderNodeWithBinding(view, 0));
|
debugSetCurrentNode(view, nextRenderNodeWithBinding(view, 0));
|
||||||
return view.def.updateRenderer(debugCheckRenderNodeFn, view);
|
return view.def.updateRenderer(debugCheckRenderNodeFn, view);
|
||||||
@ -183,35 +191,41 @@ function debugUpdateRenderer(check: NodeCheckFn, view: ViewData) {
|
|||||||
function debugCheckFn(
|
function debugCheckFn(
|
||||||
delegate: NodeCheckFn, view: ViewData, nodeIndex: number, argStyle: ArgumentType,
|
delegate: NodeCheckFn, view: ViewData, nodeIndex: number, argStyle: ArgumentType,
|
||||||
givenValues: any[]) {
|
givenValues: any[]) {
|
||||||
const values = argStyle === ArgumentType.Dynamic ? givenValues[0] : givenValues;
|
if (_currentAction === DebugAction.detectChanges) {
|
||||||
const nodeDef = view.def.nodes[nodeIndex];
|
const values = argStyle === ArgumentType.Dynamic ? givenValues[0] : givenValues;
|
||||||
for (let i = 0; i < nodeDef.bindings.length; i++) {
|
const nodeDef = view.def.nodes[nodeIndex];
|
||||||
const binding = nodeDef.bindings[i];
|
if (nodeDef.type === NodeType.Directive || nodeDef.type === NodeType.Element) {
|
||||||
const value = values[i];
|
const bindingValues: {[key: string]: string} = {};
|
||||||
if ((binding.type === BindingType.ElementProperty ||
|
for (let i = 0; i < nodeDef.bindings.length; i++) {
|
||||||
binding.type === BindingType.DirectiveProperty) &&
|
const binding = nodeDef.bindings[i];
|
||||||
checkBinding(view, nodeDef, i, value)) {
|
const value = values[i];
|
||||||
|
if ((binding.type === BindingType.ElementProperty ||
|
||||||
|
binding.type === BindingType.DirectiveProperty) &&
|
||||||
|
checkBinding(view, nodeDef, i, value)) {
|
||||||
|
bindingValues[normalizeDebugBindingName(binding.nonMinifiedName)] =
|
||||||
|
normalizeDebugBindingValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
const elDef = nodeDef.type === NodeType.Directive ? nodeDef.parent : nodeDef;
|
const elDef = nodeDef.type === NodeType.Directive ? nodeDef.parent : nodeDef;
|
||||||
setBindingDebugInfo(
|
const el = asElementData(view, elDef.index).renderElement;
|
||||||
view.root.renderer, asElementData(view, elDef.index).renderElement,
|
if (!elDef.element.name) {
|
||||||
binding.nonMinifiedName, value);
|
// a comment.
|
||||||
|
view.renderer.setValue(el, `bindings=${JSON.stringify(bindingValues, null, 2)}`);
|
||||||
|
} else {
|
||||||
|
// a regular element.
|
||||||
|
for (let attr in bindingValues) {
|
||||||
|
view.renderer.setAttribute(el, attr, bindingValues[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (<any>delegate)(view, nodeIndex, argStyle, ...givenValues);
|
return (<any>delegate)(view, nodeIndex, argStyle, ...givenValues);
|
||||||
};
|
};
|
||||||
|
|
||||||
function setBindingDebugInfo(renderer: RendererV2, renderNode: any, propName: string, value: any) {
|
function normalizeDebugBindingName(name: string) {
|
||||||
const renderName = `ng-reflect-${camelCaseToDashCase(propName)}`;
|
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
||||||
if (value) {
|
name = camelCaseToDashCase(name.replace(/\$/g, '_'));
|
||||||
try {
|
return `ng-reflect-${name}`;
|
||||||
renderer.setBindingDebugInfo(renderNode, renderName, value.toString());
|
|
||||||
} catch (e) {
|
|
||||||
renderer.setBindingDebugInfo(
|
|
||||||
renderNode, renderName, '[ERROR] Exception while trying to serialize the value');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
renderer.removeBindingDebugInfo(renderNode, renderName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
||||||
@ -220,6 +234,15 @@ function camelCaseToDashCase(input: string): string {
|
|||||||
return input.replace(CAMEL_CASE_REGEXP, (...m: any[]) => '-' + m[1].toLowerCase());
|
return input.replace(CAMEL_CASE_REGEXP, (...m: any[]) => '-' + m[1].toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeDebugBindingValue(value: any): string {
|
||||||
|
try {
|
||||||
|
// Limit the size of the value as otherwise the DOM just gets polluted.
|
||||||
|
return value ? value.toString().slice(0, 20) : value;
|
||||||
|
} catch (e) {
|
||||||
|
return '[ERROR] Exception while trying to serialize the value';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function nextDirectiveWithBinding(view: ViewData, nodeIndex: number): number {
|
function nextDirectiveWithBinding(view: ViewData, nodeIndex: number): number {
|
||||||
for (let i = nodeIndex; i < view.def.nodes.length; i++) {
|
for (let i = nodeIndex; i < view.def.nodes.length; i++) {
|
||||||
const nodeDef = view.def.nodes[i];
|
const nodeDef = view.def.nodes[i];
|
||||||
@ -241,64 +264,6 @@ function nextRenderNodeWithBinding(view: ViewData, nodeIndex: number): number {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DebugRenderer implements RendererV2 {
|
|
||||||
constructor(private _delegate: RendererV2) {}
|
|
||||||
|
|
||||||
createElement(name: string, namespace?: string): any {
|
|
||||||
return this._delegate.createElement(name, namespace, getCurrentDebugContext());
|
|
||||||
}
|
|
||||||
createComment(value: string): any {
|
|
||||||
return this._delegate.createComment(value, getCurrentDebugContext());
|
|
||||||
}
|
|
||||||
createText(value: string): any {
|
|
||||||
return this._delegate.createText(value, getCurrentDebugContext());
|
|
||||||
}
|
|
||||||
appendChild(parent: any, newChild: any): void {
|
|
||||||
return this._delegate.appendChild(parent, newChild);
|
|
||||||
}
|
|
||||||
insertBefore(parent: any, newChild: any, refChild: any): void {
|
|
||||||
return this._delegate.insertBefore(parent, newChild, refChild);
|
|
||||||
}
|
|
||||||
removeChild(parent: any, oldChild: any): void {
|
|
||||||
return this._delegate.removeChild(parent, oldChild);
|
|
||||||
}
|
|
||||||
selectRootElement(selectorOrNode: string|any): any {
|
|
||||||
return this._delegate.selectRootElement(selectorOrNode, getCurrentDebugContext());
|
|
||||||
}
|
|
||||||
parentNode(node: any): any { return this._delegate.parentNode(node); }
|
|
||||||
nextSibling(node: any): any { return this._delegate.nextSibling(node); }
|
|
||||||
setAttribute(el: any, name: string, value: string, namespace?: string): void {
|
|
||||||
return this._delegate.setAttribute(el, name, value, namespace);
|
|
||||||
}
|
|
||||||
removeAttribute(el: any, name: string, namespace?: string): void {
|
|
||||||
return this._delegate.removeAttribute(el, name, namespace);
|
|
||||||
}
|
|
||||||
setBindingDebugInfo(el: any, propertyName: string, propertyValue: string): void {
|
|
||||||
this._delegate.setBindingDebugInfo(el, propertyName, propertyValue);
|
|
||||||
}
|
|
||||||
removeBindingDebugInfo(el: any, propertyName: string): void {
|
|
||||||
this._delegate.removeBindingDebugInfo(el, propertyName);
|
|
||||||
}
|
|
||||||
addClass(el: any, name: string): void { return this._delegate.addClass(el, name); }
|
|
||||||
removeClass(el: any, name: string): void { return this._delegate.removeClass(el, name); }
|
|
||||||
setStyle(el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean):
|
|
||||||
void {
|
|
||||||
return this._delegate.setStyle(el, style, value, hasVendorPrefix, hasImportant);
|
|
||||||
}
|
|
||||||
removeStyle(el: any, style: string, hasVendorPrefix: boolean): void {
|
|
||||||
return this._delegate.removeStyle(el, style, hasVendorPrefix);
|
|
||||||
}
|
|
||||||
setProperty(el: any, name: string, value: any): void {
|
|
||||||
return this._delegate.setProperty(el, name, value);
|
|
||||||
}
|
|
||||||
setText(node: any, value: string): void { return this._delegate.setText(node, value); }
|
|
||||||
listen(
|
|
||||||
target: 'window'|'document'|'body'|any, eventName: string,
|
|
||||||
callback: (event: any) => boolean): () => void {
|
|
||||||
return this._delegate.listen(target, eventName, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DebugContext_ implements DebugContext {
|
class DebugContext_ implements DebugContext {
|
||||||
private nodeDef: NodeDef;
|
private nodeDef: NodeDef;
|
||||||
private elView: ViewData;
|
private elView: ViewData;
|
||||||
@ -401,7 +366,7 @@ function collectReferences(view: ViewData, nodeDef: NodeDef, references: {[key:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function callWithDebugContext(action: string, fn: any, self: any, args: any[]) {
|
function callWithDebugContext(action: DebugAction, fn: any, self: any, args: any[]) {
|
||||||
const oldAction = _currentAction;
|
const oldAction = _currentAction;
|
||||||
const oldView = _currentView;
|
const oldView = _currentView;
|
||||||
const oldNodeIndex = _currentNodeIndex;
|
const oldNodeIndex = _currentNodeIndex;
|
||||||
@ -421,6 +386,163 @@ function callWithDebugContext(action: string, fn: any, self: any, args: any[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentDebugContext() {
|
export function getCurrentDebugContext(): DebugContext {
|
||||||
return new DebugContext_(_currentView, _currentNodeIndex);
|
return new DebugContext_(_currentView, _currentNodeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class DebugRendererFactoryV2 implements RendererFactoryV2 {
|
||||||
|
constructor(private delegate: RendererFactoryV2) {}
|
||||||
|
|
||||||
|
createRenderer(element: any, renderData: ComponentRenderTypeV2): RendererV2 {
|
||||||
|
return new DebugRendererV2(this.delegate.createRenderer(element, renderData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class DebugRendererV2 implements RendererV2 {
|
||||||
|
constructor(private delegate: RendererV2) {}
|
||||||
|
|
||||||
|
destroyNode(node: any) {
|
||||||
|
removeDebugNodeFromIndex(getDebugNode(node));
|
||||||
|
if (this.delegate.destroyNode) {
|
||||||
|
this.delegate.destroyNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() { this.delegate.destroy(); }
|
||||||
|
|
||||||
|
createElement(name: string, namespace?: string): any {
|
||||||
|
const el = this.delegate.createElement(name, namespace);
|
||||||
|
const debugEl = new DebugElement(el, null, getCurrentDebugContext());
|
||||||
|
debugEl.name = name;
|
||||||
|
indexDebugNode(debugEl);
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
createComment(value: string): any {
|
||||||
|
const comment = this.delegate.createComment(value);
|
||||||
|
const debugEl = new DebugNode(comment, null, getCurrentDebugContext());
|
||||||
|
indexDebugNode(debugEl);
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
createText(value: string): any {
|
||||||
|
const text = this.delegate.createText(value);
|
||||||
|
const debugEl = new DebugNode(text, null, getCurrentDebugContext());
|
||||||
|
indexDebugNode(debugEl);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
appendChild(parent: any, newChild: any): void {
|
||||||
|
const debugEl = getDebugNode(parent);
|
||||||
|
const debugChildEl = getDebugNode(newChild);
|
||||||
|
if (debugEl && debugChildEl && debugEl instanceof DebugElement) {
|
||||||
|
debugEl.addChild(debugChildEl);
|
||||||
|
}
|
||||||
|
this.delegate.appendChild(parent, newChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
insertBefore(parent: any, newChild: any, refChild: any): void {
|
||||||
|
const debugEl = getDebugNode(parent);
|
||||||
|
const debugChildEl = getDebugNode(newChild);
|
||||||
|
const debugRefEl = getDebugNode(refChild);
|
||||||
|
if (debugEl && debugChildEl && debugEl instanceof DebugElement) {
|
||||||
|
debugEl.insertBefore(debugRefEl, debugChildEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.delegate.insertBefore(parent, newChild, refChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeChild(parent: any, oldChild: any): void {
|
||||||
|
const debugEl = getDebugNode(parent);
|
||||||
|
const debugChildEl = getDebugNode(oldChild);
|
||||||
|
if (debugEl && debugChildEl && debugEl instanceof DebugElement) {
|
||||||
|
debugEl.removeChild(debugChildEl);
|
||||||
|
}
|
||||||
|
this.delegate.removeChild(parent, oldChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectRootElement(selectorOrNode: string|any): any {
|
||||||
|
const el = this.delegate.selectRootElement(selectorOrNode);
|
||||||
|
const debugEl = new DebugElement(el, null, getCurrentDebugContext());
|
||||||
|
indexDebugNode(debugEl);
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAttribute(el: any, name: string, value: string, namespace?: string): void {
|
||||||
|
const debugEl = getDebugNode(el);
|
||||||
|
if (debugEl && debugEl instanceof DebugElement) {
|
||||||
|
const fullName = namespace ? namespace + ':' + name : name;
|
||||||
|
debugEl.attributes[fullName] = value;
|
||||||
|
}
|
||||||
|
this.delegate.setAttribute(el, name, value, namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeAttribute(el: any, name: string, namespace?: string): void {
|
||||||
|
const debugEl = getDebugNode(el);
|
||||||
|
if (debugEl && debugEl instanceof DebugElement) {
|
||||||
|
const fullName = namespace ? namespace + ':' + name : name;
|
||||||
|
debugEl.attributes[fullName] = null;
|
||||||
|
}
|
||||||
|
this.delegate.removeAttribute(el, name, namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
addClass(el: any, name: string): void {
|
||||||
|
const debugEl = getDebugNode(el);
|
||||||
|
if (debugEl && debugEl instanceof DebugElement) {
|
||||||
|
debugEl.classes[name] = true;
|
||||||
|
}
|
||||||
|
this.delegate.addClass(el, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeClass(el: any, name: string): void {
|
||||||
|
const debugEl = getDebugNode(el);
|
||||||
|
if (debugEl && debugEl instanceof DebugElement) {
|
||||||
|
debugEl.classes[name] = false;
|
||||||
|
}
|
||||||
|
this.delegate.removeClass(el, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
setStyle(el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean):
|
||||||
|
void {
|
||||||
|
const debugEl = getDebugNode(el);
|
||||||
|
if (debugEl && debugEl instanceof DebugElement) {
|
||||||
|
debugEl.styles[style] = value;
|
||||||
|
}
|
||||||
|
this.delegate.setStyle(el, style, value, hasVendorPrefix, hasImportant);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeStyle(el: any, style: string, hasVendorPrefix: boolean): void {
|
||||||
|
const debugEl = getDebugNode(el);
|
||||||
|
if (debugEl && debugEl instanceof DebugElement) {
|
||||||
|
debugEl.styles[style] = null;
|
||||||
|
}
|
||||||
|
this.delegate.removeStyle(el, style, hasVendorPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
setProperty(el: any, name: string, value: any): void {
|
||||||
|
const debugEl = getDebugNode(el);
|
||||||
|
if (debugEl && debugEl instanceof DebugElement) {
|
||||||
|
debugEl.properties[name] = value;
|
||||||
|
}
|
||||||
|
this.delegate.setProperty(el, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(
|
||||||
|
target: 'document'|'windows'|'body'|any, eventName: string,
|
||||||
|
callback: (event: any) => boolean): () => void {
|
||||||
|
if (typeof target !== 'string') {
|
||||||
|
const debugEl = getDebugNode(target);
|
||||||
|
if (debugEl) {
|
||||||
|
debugEl.listeners.push(new EventListener(eventName, callback));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.delegate.listen(target, eventName, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
parentNode(node: any): any { return this.delegate.parentNode(node); }
|
||||||
|
nextSibling(node: any): any { return this.delegate.nextSibling(node); }
|
||||||
|
setValue(node: any, value: string): void { return this.delegate.setValue(node, value); }
|
||||||
|
}
|
||||||
|
@ -54,7 +54,7 @@ export function textDef(ngContentIndex: number, constants: string[]): NodeDef {
|
|||||||
|
|
||||||
export function createText(view: ViewData, renderHost: any, def: NodeDef): TextData {
|
export function createText(view: ViewData, renderHost: any, def: NodeDef): TextData {
|
||||||
let renderNode: any;
|
let renderNode: any;
|
||||||
const renderer = view.root.renderer;
|
const renderer = view.renderer;
|
||||||
renderNode = renderer.createText(def.text.prefix);
|
renderNode = renderer.createText(def.text.prefix);
|
||||||
const parentEl = getParentRenderElement(view, renderHost, def);
|
const parentEl = getParentRenderElement(view, renderHost, def);
|
||||||
if (parentEl) {
|
if (parentEl) {
|
||||||
@ -119,7 +119,7 @@ export function checkAndUpdateTextInline(
|
|||||||
}
|
}
|
||||||
value = def.text.prefix + value;
|
value = def.text.prefix + value;
|
||||||
const renderNode = asTextData(view, def.index).renderText;
|
const renderNode = asTextData(view, def.index).renderText;
|
||||||
view.root.renderer.setText(renderNode, value);
|
view.renderer.setValue(renderNode, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ export function checkAndUpdateTextDynamic(view: ViewData, def: NodeDef, values:
|
|||||||
}
|
}
|
||||||
value = def.text.prefix + value;
|
value = def.text.prefix + value;
|
||||||
const renderNode = asTextData(view, def.index).renderText;
|
const renderNode = asTextData(view, def.index).renderText;
|
||||||
view.root.renderer.setText(renderNode, value);
|
view.renderer.setValue(renderNode, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import {TemplateRef} from '../linker/template_ref';
|
|||||||
import {ViewContainerRef} from '../linker/view_container_ref';
|
import {ViewContainerRef} from '../linker/view_container_ref';
|
||||||
import {ViewRef} from '../linker/view_ref';
|
import {ViewRef} from '../linker/view_ref';
|
||||||
import {ViewEncapsulation} from '../metadata/view';
|
import {ViewEncapsulation} from '../metadata/view';
|
||||||
import {RenderDebugContext, RendererV2} from '../render/api';
|
import {ComponentRenderTypeV2, RendererFactoryV2, RendererV2} from '../render/api';
|
||||||
import {Sanitizer, SecurityContext} from '../security';
|
import {Sanitizer, SecurityContext} from '../security';
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
@ -23,7 +23,6 @@ import {Sanitizer, SecurityContext} from '../security';
|
|||||||
|
|
||||||
export interface ViewDefinition {
|
export interface ViewDefinition {
|
||||||
flags: ViewFlags;
|
flags: ViewFlags;
|
||||||
component: ComponentDefinition;
|
|
||||||
updateDirectives: ViewUpdateFn;
|
updateDirectives: ViewUpdateFn;
|
||||||
updateRenderer: ViewUpdateFn;
|
updateRenderer: ViewUpdateFn;
|
||||||
handleEvent: ViewHandleEventFn;
|
handleEvent: ViewHandleEventFn;
|
||||||
@ -75,13 +74,7 @@ export enum ArgumentType {
|
|||||||
*/
|
*/
|
||||||
export enum ViewFlags {
|
export enum ViewFlags {
|
||||||
None = 0,
|
None = 0,
|
||||||
OnPush = 1 << 1
|
OnPush = 1 << 1,
|
||||||
}
|
|
||||||
|
|
||||||
export interface ComponentDefinition {
|
|
||||||
id: string;
|
|
||||||
encapsulation: ViewEncapsulation;
|
|
||||||
styles: string[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -223,6 +216,7 @@ export interface ProviderDef {
|
|||||||
value: any;
|
value: any;
|
||||||
deps: DepDef[];
|
deps: DepDef[];
|
||||||
outputs: DirectiveOutputDef[];
|
outputs: DirectiveOutputDef[];
|
||||||
|
componentRenderType: ComponentRenderTypeV2;
|
||||||
// closure to allow recursive components
|
// closure to allow recursive components
|
||||||
component: ViewDefinitionFactory;
|
component: ViewDefinitionFactory;
|
||||||
}
|
}
|
||||||
@ -306,6 +300,7 @@ export interface NgContentDef {
|
|||||||
export interface ViewData {
|
export interface ViewData {
|
||||||
def: ViewDefinition;
|
def: ViewDefinition;
|
||||||
root: RootData;
|
root: RootData;
|
||||||
|
renderer: RendererV2;
|
||||||
// index of component provider / anchor.
|
// index of component provider / anchor.
|
||||||
parentNodeDef: NodeDef;
|
parentNodeDef: NodeDef;
|
||||||
parent: ViewData;
|
parent: ViewData;
|
||||||
@ -426,12 +421,21 @@ export interface RootData {
|
|||||||
projectableNodes: any[][];
|
projectableNodes: any[][];
|
||||||
selectorOrNode: any;
|
selectorOrNode: any;
|
||||||
renderer: RendererV2;
|
renderer: RendererV2;
|
||||||
|
rendererFactory: RendererFactoryV2;
|
||||||
sanitizer: Sanitizer;
|
sanitizer: Sanitizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class DebugContext extends RenderDebugContext {
|
export abstract class DebugContext {
|
||||||
abstract get view(): ViewData;
|
abstract get view(): ViewData;
|
||||||
abstract get nodeIndex(): number;
|
abstract get nodeIndex(): number;
|
||||||
|
abstract get injector(): Injector;
|
||||||
|
abstract get component(): any;
|
||||||
|
abstract get providerTokens(): any[];
|
||||||
|
abstract get references(): {[key: string]: any};
|
||||||
|
abstract get context(): any;
|
||||||
|
abstract get source(): string;
|
||||||
|
abstract get componentRenderElement(): any;
|
||||||
|
abstract get renderNode(): any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
@ -14,7 +14,8 @@ import {looseIdentical, stringify} from '../facade/lang';
|
|||||||
import {TemplateRef} from '../linker/template_ref';
|
import {TemplateRef} from '../linker/template_ref';
|
||||||
import {ViewContainerRef} from '../linker/view_container_ref';
|
import {ViewContainerRef} from '../linker/view_container_ref';
|
||||||
import {ViewRef} from '../linker/view_ref';
|
import {ViewRef} from '../linker/view_ref';
|
||||||
import {Renderer} from '../render/api';
|
import {ViewEncapsulation} from '../metadata/view';
|
||||||
|
import {ComponentRenderTypeV2, Renderer} from '../render/api';
|
||||||
|
|
||||||
import {expressionChangedAfterItHasBeenCheckedError, isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors';
|
import {expressionChangedAfterItHasBeenCheckedError, isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors';
|
||||||
import {DebugContext, ElementData, NodeData, NodeDef, NodeFlags, NodeType, QueryValueType, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewState, asElementData, asProviderData, asTextData} from './types';
|
import {DebugContext, ElementData, NodeData, NodeDef, NodeFlags, NodeType, QueryValueType, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewState, asElementData, asProviderData, asTextData} from './types';
|
||||||
@ -40,6 +41,23 @@ export function unwrapValue(value: any): any {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let _renderCompCount = 0;
|
||||||
|
|
||||||
|
export function createComponentRenderTypeV2(values: {
|
||||||
|
styles: (string | any[])[],
|
||||||
|
encapsulation: ViewEncapsulation,
|
||||||
|
data: {[kind: string]: any[]}
|
||||||
|
}): ComponentRenderTypeV2 {
|
||||||
|
const isFilled = values && (values.encapsulation !== ViewEncapsulation.None ||
|
||||||
|
values.styles.length || Object.keys(values.data).length);
|
||||||
|
if (isFilled) {
|
||||||
|
const id = `c${_renderCompCount++}`;
|
||||||
|
return {id: id, styles: values.styles, encapsulation: values.encapsulation, data: values.data};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function checkBinding(
|
export function checkBinding(
|
||||||
view: ViewData, def: NodeDef, bindingIdx: number, value: any): boolean {
|
view: ViewData, def: NodeDef, bindingIdx: number, value: any): boolean {
|
||||||
const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
|
const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
|
||||||
@ -220,7 +238,7 @@ export function visitRootRenderNodes(
|
|||||||
view: ViewData, action: RenderNodeAction, parentNode: any, nextSibling: any, target: any[]) {
|
view: ViewData, action: RenderNodeAction, parentNode: any, nextSibling: any, target: any[]) {
|
||||||
// We need to re-compute the parent node in case the nodes have been moved around manually
|
// We need to re-compute the parent node in case the nodes have been moved around manually
|
||||||
if (action === RenderNodeAction.RemoveChild) {
|
if (action === RenderNodeAction.RemoveChild) {
|
||||||
parentNode = view.root.renderer.parentNode(renderNode(view, view.def.lastRootNode));
|
parentNode = view.renderer.parentNode(renderNode(view, view.def.lastRootNode));
|
||||||
}
|
}
|
||||||
visitSiblingRenderNodes(
|
visitSiblingRenderNodes(
|
||||||
view, action, 0, view.def.nodes.length - 1, parentNode, nextSibling, target);
|
view, action, 0, view.def.nodes.length - 1, parentNode, nextSibling, target);
|
||||||
@ -298,7 +316,7 @@ function visitRenderNode(
|
|||||||
function execRenderNodeAction(
|
function execRenderNodeAction(
|
||||||
view: ViewData, renderNode: any, action: RenderNodeAction, parentNode: any, nextSibling: any,
|
view: ViewData, renderNode: any, action: RenderNodeAction, parentNode: any, nextSibling: any,
|
||||||
target: any[]) {
|
target: any[]) {
|
||||||
const renderer = view.root.renderer;
|
const renderer = view.renderer;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case RenderNodeAction.AppendChild:
|
case RenderNodeAction.AppendChild:
|
||||||
renderer.appendChild(parentNode, renderNode);
|
renderer.appendChild(parentNode, renderNode);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {ViewEncapsulation} from '../metadata/view';
|
import {ViewEncapsulation} from '../metadata/view';
|
||||||
|
import {ComponentRenderTypeV2, RendererV2} from '../render/api';
|
||||||
|
|
||||||
import {checkAndUpdateElementDynamic, checkAndUpdateElementInline, createElement} from './element';
|
import {checkAndUpdateElementDynamic, checkAndUpdateElementInline, createElement} from './element';
|
||||||
import {expressionChangedAfterItHasBeenCheckedError} from './errors';
|
import {expressionChangedAfterItHasBeenCheckedError} from './errors';
|
||||||
@ -15,15 +16,14 @@ import {callLifecycleHooksChildrenFirst, checkAndUpdateDirectiveDynamic, checkAn
|
|||||||
import {checkAndUpdatePureExpressionDynamic, checkAndUpdatePureExpressionInline, createPureExpression} from './pure_expression';
|
import {checkAndUpdatePureExpressionDynamic, checkAndUpdatePureExpressionInline, createPureExpression} from './pure_expression';
|
||||||
import {checkAndUpdateQuery, createQuery, queryDef} from './query';
|
import {checkAndUpdateQuery, createQuery, queryDef} from './query';
|
||||||
import {checkAndUpdateTextDynamic, checkAndUpdateTextInline, createText} from './text';
|
import {checkAndUpdateTextDynamic, checkAndUpdateTextInline, createText} from './text';
|
||||||
import {ArgumentType, ComponentDefinition, ElementDef, NodeData, NodeDef, NodeFlags, NodeType, ProviderData, ProviderDef, RootData, Services, TextDef, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, asElementData, asProviderData, asPureExpressionData, asQueryList} from './types';
|
import {ArgumentType, ElementDef, NodeData, NodeDef, NodeFlags, NodeType, ProviderData, ProviderDef, RootData, Services, TextDef, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, asElementData, asProviderData, asPureExpressionData, asQueryList, asTextData} from './types';
|
||||||
import {checkBindingNoChanges, isComponentView, resolveViewDefinition, viewParentEl} from './util';
|
import {checkBindingNoChanges, isComponentView, resolveViewDefinition, viewParentEl} from './util';
|
||||||
|
|
||||||
const NOOP = (): any => undefined;
|
const NOOP = (): any => undefined;
|
||||||
|
|
||||||
export function viewDef(
|
export function viewDef(
|
||||||
flags: ViewFlags, nodes: NodeDef[], updateDirectives?: ViewUpdateFn,
|
flags: ViewFlags, nodes: NodeDef[], updateDirectives?: ViewUpdateFn,
|
||||||
updateRenderer?: ViewUpdateFn, handleEvent?: ViewHandleEventFn, compId?: string,
|
updateRenderer?: ViewUpdateFn, handleEvent?: ViewHandleEventFn): ViewDefinition {
|
||||||
encapsulation?: ViewEncapsulation, styles?: string[]): ViewDefinition {
|
|
||||||
// clone nodes and set auto calculated values
|
// clone nodes and set auto calculated values
|
||||||
if (nodes.length === 0) {
|
if (nodes.length === 0) {
|
||||||
throw new Error(`Illegal State: Views without nodes are not allowed!`);
|
throw new Error(`Illegal State: Views without nodes are not allowed!`);
|
||||||
@ -57,8 +57,11 @@ export function viewDef(
|
|||||||
|
|
||||||
let currentRenderParent: NodeDef;
|
let currentRenderParent: NodeDef;
|
||||||
if (currentParent &&
|
if (currentParent &&
|
||||||
!(currentParent.type === NodeType.Element && currentParent.element.component)) {
|
(currentParent.type !== NodeType.Element || !currentParent.element.component ||
|
||||||
// children of components should never be attached!
|
(currentParent.element.component.provider.componentRenderType &&
|
||||||
|
currentParent.element.component.provider.componentRenderType.encapsulation ===
|
||||||
|
ViewEncapsulation.Native))) {
|
||||||
|
// children of components that don't use native encapsulation should never be attached!
|
||||||
if (currentParent && currentParent.type === NodeType.Element && !currentParent.element.name) {
|
if (currentParent && currentParent.type === NodeType.Element && !currentParent.element.name) {
|
||||||
currentRenderParent = currentParent.renderParent;
|
currentRenderParent = currentParent.renderParent;
|
||||||
} else {
|
} else {
|
||||||
@ -134,8 +137,6 @@ export function viewDef(
|
|||||||
}
|
}
|
||||||
currentParent = newParent;
|
currentParent = newParent;
|
||||||
}
|
}
|
||||||
const componentDef =
|
|
||||||
compId ? <ComponentDefinition>{id: compId, encapsulation, styles} : undefined;
|
|
||||||
return {
|
return {
|
||||||
nodeFlags: viewNodeFlags,
|
nodeFlags: viewNodeFlags,
|
||||||
nodeMatchedQueries: viewMatchedQueries, flags,
|
nodeMatchedQueries: viewMatchedQueries, flags,
|
||||||
@ -143,7 +144,6 @@ export function viewDef(
|
|||||||
updateDirectives: updateDirectives || NOOP,
|
updateDirectives: updateDirectives || NOOP,
|
||||||
updateRenderer: updateRenderer || NOOP,
|
updateRenderer: updateRenderer || NOOP,
|
||||||
handleEvent: handleEvent || NOOP,
|
handleEvent: handleEvent || NOOP,
|
||||||
component: componentDef,
|
|
||||||
bindingCount: viewBindingCount,
|
bindingCount: viewBindingCount,
|
||||||
disposableCount: viewDisposableCount, lastRootNode
|
disposableCount: viewDisposableCount, lastRootNode
|
||||||
};
|
};
|
||||||
@ -222,21 +222,23 @@ function validateNode(parent: NodeDef, node: NodeDef, nodeCount: number) {
|
|||||||
export function createEmbeddedView(parent: ViewData, anchorDef: NodeDef, context?: any): ViewData {
|
export function createEmbeddedView(parent: ViewData, anchorDef: NodeDef, context?: any): ViewData {
|
||||||
// embedded views are seen as siblings to the anchor, so we need
|
// embedded views are seen as siblings to the anchor, so we need
|
||||||
// to get the parent of the anchor and use it as parentIndex.
|
// to get the parent of the anchor and use it as parentIndex.
|
||||||
const view = createView(parent.root, parent, anchorDef, anchorDef.element.template);
|
const view =
|
||||||
|
createView(parent.root, parent.renderer, parent, anchorDef, anchorDef.element.template);
|
||||||
initView(view, parent.component, context);
|
initView(view, parent.component, context);
|
||||||
createViewNodes(view);
|
createViewNodes(view);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createRootView(root: RootData, def: ViewDefinition, context?: any): ViewData {
|
export function createRootView(root: RootData, def: ViewDefinition, context?: any): ViewData {
|
||||||
const view = createView(root, null, null, def);
|
const view = createView(root, root.renderer, null, null, def);
|
||||||
initView(view, context, context);
|
initView(view, context, context);
|
||||||
createViewNodes(view);
|
createViewNodes(view);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createView(
|
function createView(
|
||||||
root: RootData, parent: ViewData, parentNodeDef: NodeDef, def: ViewDefinition): ViewData {
|
root: RootData, renderer: RendererV2, parent: ViewData, parentNodeDef: NodeDef,
|
||||||
|
def: ViewDefinition): ViewData {
|
||||||
const nodes: NodeData[] = new Array(def.nodes.length);
|
const nodes: NodeData[] = new Array(def.nodes.length);
|
||||||
const disposables = def.disposableCount ? new Array(def.disposableCount) : undefined;
|
const disposables = def.disposableCount ? new Array(def.disposableCount) : undefined;
|
||||||
const view: ViewData = {
|
const view: ViewData = {
|
||||||
@ -245,7 +247,7 @@ function createView(
|
|||||||
parentNodeDef,
|
parentNodeDef,
|
||||||
context: undefined,
|
context: undefined,
|
||||||
component: undefined, nodes,
|
component: undefined, nodes,
|
||||||
state: ViewState.FirstCheck | ViewState.ChecksEnabled, root,
|
state: ViewState.FirstCheck | ViewState.ChecksEnabled, root, renderer,
|
||||||
oldValues: new Array(def.bindingCount), disposables
|
oldValues: new Array(def.bindingCount), disposables
|
||||||
};
|
};
|
||||||
return view;
|
return view;
|
||||||
@ -259,9 +261,9 @@ function initView(view: ViewData, component: any, context: any) {
|
|||||||
function createViewNodes(view: ViewData) {
|
function createViewNodes(view: ViewData) {
|
||||||
let renderHost: any;
|
let renderHost: any;
|
||||||
if (isComponentView(view)) {
|
if (isComponentView(view)) {
|
||||||
renderHost = asElementData(view.parent, viewParentEl(view).index).renderElement;
|
const hostDef = view.parentNodeDef;
|
||||||
|
renderHost = asElementData(view.parent, hostDef.parent.index).renderElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
const def = view.def;
|
const def = view.def;
|
||||||
const nodes = view.nodes;
|
const nodes = view.nodes;
|
||||||
for (let i = 0; i < def.nodes.length; i++) {
|
for (let i = 0; i < def.nodes.length; i++) {
|
||||||
@ -291,8 +293,16 @@ function createViewNodes(view: ViewData) {
|
|||||||
// Components can inject a ChangeDetectorRef that needs a references to
|
// Components can inject a ChangeDetectorRef that needs a references to
|
||||||
// the component view. Therefore, we create the component view first
|
// the component view. Therefore, we create the component view first
|
||||||
// and set the ProviderData in ViewData, and then instantiate the provider.
|
// and set the ProviderData in ViewData, and then instantiate the provider.
|
||||||
const componentView = createView(
|
const compViewDef = resolveViewDefinition(nodeDef.provider.component);
|
||||||
view.root, view, nodeDef, resolveViewDefinition(nodeDef.provider.component));
|
const compRenderType = nodeDef.provider.componentRenderType;
|
||||||
|
let compRenderer: RendererV2;
|
||||||
|
if (!compRenderType) {
|
||||||
|
compRenderer = view.root.renderer;
|
||||||
|
} else {
|
||||||
|
const hostEl = asElementData(view, nodeDef.parent.index).renderElement;
|
||||||
|
compRenderer = view.root.rendererFactory.createRenderer(hostEl, compRenderType);
|
||||||
|
}
|
||||||
|
const componentView = createView(view.root, compRenderer, view, nodeDef, compViewDef);
|
||||||
const providerData = <ProviderData>{componentView, instance: undefined};
|
const providerData = <ProviderData>{componentView, instance: undefined};
|
||||||
nodes[i] = providerData as any;
|
nodes[i] = providerData as any;
|
||||||
const instance = providerData.instance = createDirectiveInstance(view, nodeDef);
|
const instance = providerData.instance = createDirectiveInstance(view, nodeDef);
|
||||||
@ -473,9 +483,27 @@ export function destroyView(view: ViewData) {
|
|||||||
view.disposables[i]();
|
view.disposables[i]();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (view.renderer.destroyNode) {
|
||||||
|
destroyViewNodes(view);
|
||||||
|
}
|
||||||
|
if (view.parentNodeDef && view.parentNodeDef.flags & NodeFlags.HasComponent) {
|
||||||
|
view.renderer.destroy();
|
||||||
|
}
|
||||||
view.state |= ViewState.Destroyed;
|
view.state |= ViewState.Destroyed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function destroyViewNodes(view: ViewData) {
|
||||||
|
const len = view.def.nodes.length;
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
const def = view.def.nodes[i];
|
||||||
|
if (def.type === NodeType.Element) {
|
||||||
|
view.renderer.destroyNode(asElementData(view, i).renderElement);
|
||||||
|
} else if (def.type === NodeType.Text) {
|
||||||
|
view.renderer.destroyNode(asTextData(view, i).renderText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum ViewAction {
|
enum ViewAction {
|
||||||
CreateViewNodes,
|
CreateViewNodes,
|
||||||
CheckNoChanges,
|
CheckNoChanges,
|
||||||
|
@ -77,15 +77,15 @@ export function moveEmbeddedView(
|
|||||||
function renderAttachEmbeddedView(elementData: ElementData, prevView: ViewData, view: ViewData) {
|
function renderAttachEmbeddedView(elementData: ElementData, prevView: ViewData, view: ViewData) {
|
||||||
const prevRenderNode =
|
const prevRenderNode =
|
||||||
prevView ? renderNode(prevView, prevView.def.lastRootNode) : elementData.renderElement;
|
prevView ? renderNode(prevView, prevView.def.lastRootNode) : elementData.renderElement;
|
||||||
const parentNode = view.root.renderer.parentNode(prevRenderNode);
|
const parentNode = view.renderer.parentNode(prevRenderNode);
|
||||||
const nextSibling = view.root.renderer.nextSibling(prevRenderNode);
|
const nextSibling = view.renderer.nextSibling(prevRenderNode);
|
||||||
// Note: We can't check if `nextSibling` is present, as on WebWorkers it will always be!
|
// Note: We can't check if `nextSibling` is present, as on WebWorkers it will always be!
|
||||||
// However, browsers automatically do `appendChild` when there is no `nextSibling`.
|
// However, browsers automatically do `appendChild` when there is no `nextSibling`.
|
||||||
visitRootRenderNodes(view, RenderNodeAction.InsertBefore, parentNode, nextSibling, undefined);
|
visitRootRenderNodes(view, RenderNodeAction.InsertBefore, parentNode, nextSibling, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderDetachEmbeddedView(elementData: ElementData, view: ViewData) {
|
function renderDetachEmbeddedView(elementData: ElementData, view: ViewData) {
|
||||||
const parentNode = view.root.renderer.parentNode(elementData.renderElement);
|
const parentNode = view.renderer.parentNode(elementData.renderElement);
|
||||||
visitRootRenderNodes(view, RenderNodeAction.RemoveChild, parentNode, null, undefined);
|
visitRootRenderNodes(view, RenderNodeAction.RemoveChild, parentNode, null, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
import {USE_VIEW_ENGINE} from '@angular/compiler/src/config';
|
import {USE_VIEW_ENGINE} from '@angular/compiler/src/config';
|
||||||
import {ElementSchemaRegistry} from '@angular/compiler/src/schema/element_schema_registry';
|
import {ElementSchemaRegistry} from '@angular/compiler/src/schema/element_schema_registry';
|
||||||
import {TEST_COMPILER_PROVIDERS} from '@angular/compiler/testing/test_bindings';
|
import {TEST_COMPILER_PROVIDERS} from '@angular/compiler/testing/test_bindings';
|
||||||
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, DebugElement, Directive, DoCheck, Inject, Injectable, Input, OnChanges, OnDestroy, OnInit, Output, Pipe, PipeTransform, RENDERER_V2_DIRECT, RenderComponentType, Renderer, RendererV2, RootRenderer, SimpleChange, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef, WrappedValue} from '@angular/core';
|
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, DebugElement, Directive, DoCheck, Inject, Injectable, Input, OnChanges, OnDestroy, OnInit, Output, Pipe, PipeTransform, RenderComponentType, Renderer, RendererFactoryV2, RootRenderer, SimpleChange, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef, WrappedValue} from '@angular/core';
|
||||||
import {DebugDomRenderer, DebugDomRendererV2} from '@angular/core/src/debug/debug_renderer';
|
import {DebugDomRenderer} from '@angular/core/src/debug/debug_renderer';
|
||||||
import {ComponentFixture, TestBed, fakeAsync} from '@angular/core/testing';
|
import {ComponentFixture, TestBed, fakeAsync} from '@angular/core/testing';
|
||||||
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
||||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||||
@ -57,6 +57,7 @@ function createTests({viewEngine}: {viewEngine: boolean}) {
|
|||||||
renderLog = TestBed.get(RenderLog);
|
renderLog = TestBed.get(RenderLog);
|
||||||
directiveLog = TestBed.get(DirectiveLog);
|
directiveLog = TestBed.get(DirectiveLog);
|
||||||
elSchema.existingProperties['someProp'] = true;
|
elSchema.existingProperties['someProp'] = true;
|
||||||
|
patchLoggingRendererV2(TestBed.get(RendererFactoryV2), renderLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryDirs(el: DebugElement, dirType: Type<any>): any {
|
function queryDirs(el: DebugElement, dirType: Type<any>): any {
|
||||||
@ -123,11 +124,6 @@ function createTests({viewEngine}: {viewEngine: boolean}) {
|
|||||||
RenderLog,
|
RenderLog,
|
||||||
DirectiveLog,
|
DirectiveLog,
|
||||||
{provide: RootRenderer, useClass: LoggingRootRenderer},
|
{provide: RootRenderer, useClass: LoggingRootRenderer},
|
||||||
{
|
|
||||||
provide: RendererV2,
|
|
||||||
useFactory: (r: RendererV2, log: RenderLog) => new LoggingRendererV2(r, log),
|
|
||||||
deps: [[new Inject(RENDERER_V2_DIRECT)], [RenderLog]],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1244,28 +1240,26 @@ function createTests({viewEngine}: {viewEngine: boolean}) {
|
|||||||
expect(renderLog.loggedValues).toEqual(['Tom']);
|
expect(renderLog.loggedValues).toEqual(['Tom']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO(tbosch): ViewQueries don't work yet with the view engine...
|
it('should recurse into nested view containers even if there are no bindings in the component view',
|
||||||
viewEngine ||
|
() => {
|
||||||
it('should recurse into nested view containers even if there are no bindings in the component view',
|
@Component({template: '<template #vc>{{name}}</template>'})
|
||||||
() => {
|
class Comp {
|
||||||
@Component({template: '<template #vc>{{name}}</template>'})
|
name = 'Tom';
|
||||||
class Comp {
|
@ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;
|
||||||
name = 'Tom';
|
@ViewChild(TemplateRef) template: TemplateRef<any>;
|
||||||
@ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;
|
}
|
||||||
@ViewChild(TemplateRef) template: TemplateRef<any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [Comp]});
|
TestBed.configureTestingModule({declarations: [Comp]});
|
||||||
initHelpers();
|
initHelpers();
|
||||||
|
|
||||||
const ctx = TestBed.createComponent(Comp);
|
const ctx = TestBed.createComponent(Comp);
|
||||||
ctx.detectChanges();
|
ctx.detectChanges();
|
||||||
expect(renderLog.loggedValues).toEqual([]);
|
expect(renderLog.loggedValues).toEqual([]);
|
||||||
|
|
||||||
ctx.componentInstance.vc.createEmbeddedView(ctx.componentInstance.template);
|
ctx.componentInstance.vc.createEmbeddedView(ctx.componentInstance.template);
|
||||||
ctx.detectChanges();
|
ctx.detectChanges();
|
||||||
expect(renderLog.loggedValues).toEqual(['Tom']);
|
expect(renderLog.loggedValues).toEqual(['Tom']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1315,18 +1309,32 @@ class DirectiveLogEntry {
|
|||||||
constructor(public directiveName: string, public method: string) {}
|
constructor(public directiveName: string, public method: string) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoggingRendererV2 extends DebugDomRendererV2 {
|
function patchLoggingRendererV2(rendererFactory: RendererFactoryV2, log: RenderLog) {
|
||||||
constructor(private delegate: RendererV2, private log: RenderLog) { super(delegate); }
|
if ((<any>rendererFactory).__patchedForLogging) {
|
||||||
|
return;
|
||||||
setProperty(el: any, name: string, value: any): void {
|
|
||||||
this.log.setElementProperty(el, name, value);
|
|
||||||
super.setProperty(el, name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
setText(node: any, value: string): void {
|
|
||||||
this.log.setText(node, value);
|
|
||||||
super.setText(node, value);
|
|
||||||
}
|
}
|
||||||
|
(<any>rendererFactory).__patchedForLogging = true;
|
||||||
|
const origCreateRenderer = rendererFactory.createRenderer;
|
||||||
|
rendererFactory.createRenderer = function() {
|
||||||
|
const renderer = origCreateRenderer.apply(this, arguments);
|
||||||
|
if ((<any>renderer).__patchedForLogging) {
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
(<any>renderer).__patchedForLogging = true;
|
||||||
|
const origSetProperty = renderer.setProperty;
|
||||||
|
const origSetValue = renderer.setValue;
|
||||||
|
renderer.setProperty = function(el: any, name: string, value: any): void {
|
||||||
|
log.setElementProperty(el, name, value);
|
||||||
|
origSetProperty.call(this, el, name, value);
|
||||||
|
};
|
||||||
|
renderer.setValue = function(node: any, value: string): void {
|
||||||
|
if (getDOM().isTextNode(node)) {
|
||||||
|
log.setText(node, value);
|
||||||
|
}
|
||||||
|
origSetValue.call(this, node, value);
|
||||||
|
};
|
||||||
|
return renderer;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -1515,7 +1515,7 @@ function declareTests({useJit, viewEngine}: {useJit: boolean, viewEngine: boolea
|
|||||||
const fixture = TestBed.createComponent(ParentCmp);
|
const fixture = TestBed.createComponent(ParentCmp);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(getDOM().getInnerHTML(fixture.nativeElement)).toContain('ng-reflect-test$="hello"');
|
expect(getDOM().getInnerHTML(fixture.nativeElement)).toContain('ng-reflect-test_="hello"');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reflect property values on template comments', () => {
|
it('should reflect property values on template comments', () => {
|
||||||
|
@ -378,7 +378,7 @@ function createTests({viewEngine}: {viewEngine: boolean}) {
|
|||||||
expect(main.nativeElement).toHaveText('TREE(0:TREE2(1:TREE(2:)))');
|
expect(main.nativeElement).toHaveText('TREE(0:TREE2(1:TREE(2:)))');
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!viewEngine && getDOM().supportsNativeShadowDOM()) {
|
if (getDOM().supportsNativeShadowDOM()) {
|
||||||
it('should support native content projection and isolate styles per component', () => {
|
it('should support native content projection and isolate styles per component', () => {
|
||||||
TestBed.configureTestingModule({declarations: [SimpleNative1, SimpleNative2]});
|
TestBed.configureTestingModule({declarations: [SimpleNative1, SimpleNative2]});
|
||||||
TestBed.overrideComponent(MainComp, {
|
TestBed.overrideComponent(MainComp, {
|
||||||
@ -396,7 +396,7 @@ function createTests({viewEngine}: {viewEngine: boolean}) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!viewEngine && getDOM().supportsDOMEvents()) {
|
if (getDOM().supportsDOMEvents()) {
|
||||||
it('should support non emulated styles', () => {
|
it('should support non emulated styles', () => {
|
||||||
TestBed.configureTestingModule({declarations: [OtherComp]});
|
TestBed.configureTestingModule({declarations: [OtherComp]});
|
||||||
TestBed.overrideComponent(MainComp, {
|
TestBed.overrideComponent(MainComp, {
|
||||||
|
@ -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 {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectorRef, DoCheck, ElementRef, EventEmitter, Injector, OnChanges, OnDestroy, OnInit, RenderComponentType, Renderer, RootRenderer, Sanitizer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core';
|
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectorRef, DoCheck, ElementRef, EventEmitter, Injector, OnChanges, OnDestroy, OnInit, RenderComponentType, Renderer, RendererV2, RootRenderer, Sanitizer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core';
|
||||||
import {getDebugContext} from '@angular/core/src/errors';
|
import {getDebugContext} from '@angular/core/src/errors';
|
||||||
import {ArgumentType, BindingType, DebugContext, DepFlags, NodeDef, NodeFlags, ProviderType, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, directiveDef, elementDef, providerDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
|
import {ArgumentType, BindingType, DebugContext, DepFlags, NodeDef, NodeFlags, ProviderType, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, directiveDef, elementDef, providerDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index';
|
||||||
import {TestBed, inject, withModule} from '@angular/core/testing';
|
import {TestBed, inject, withModule} from '@angular/core/testing';
|
||||||
@ -19,9 +19,7 @@ export function main() {
|
|||||||
function compViewDef(
|
function compViewDef(
|
||||||
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
|
nodes: NodeDef[], updateDirectives?: ViewUpdateFn, updateRenderer?: ViewUpdateFn,
|
||||||
handleEvent?: ViewHandleEventFn, viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
|
handleEvent?: ViewHandleEventFn, viewFlags: ViewFlags = ViewFlags.None): ViewDefinition {
|
||||||
return viewDef(
|
return viewDef(viewFlags, nodes, updateDirectives, updateRenderer, handleEvent);
|
||||||
viewFlags, nodes, updateDirectives, updateRenderer, handleEvent, 'someCompId',
|
|
||||||
ViewEncapsulation.None, []);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinitionFactory {
|
function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinitionFactory {
|
||||||
@ -292,11 +290,25 @@ export function main() {
|
|||||||
it('should inject RendererV1', () => {
|
it('should inject RendererV1', () => {
|
||||||
createAndGetRootNodes(compViewDef([
|
createAndGetRootNodes(compViewDef([
|
||||||
elementDef(NodeFlags.None, null, null, 1, 'span'),
|
elementDef(NodeFlags.None, null, null, 1, 'span'),
|
||||||
directiveDef(NodeFlags.None, null, 0, SomeService, [Renderer])
|
directiveDef(
|
||||||
|
NodeFlags.None, null, 0, SomeService, [Renderer], null, null,
|
||||||
|
() => compViewDef([anchorDef(NodeFlags.None, null, null, 0)]))
|
||||||
]));
|
]));
|
||||||
|
|
||||||
expect(instance.dep.createElement).toBeTruthy();
|
expect(instance.dep.createElement).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should inject RendererV2', () => {
|
||||||
|
createAndGetRootNodes(compViewDef([
|
||||||
|
elementDef(NodeFlags.None, null, null, 1, 'span'),
|
||||||
|
directiveDef(
|
||||||
|
NodeFlags.None, null, 0, SomeService, [RendererV2], null, null,
|
||||||
|
() => compViewDef([anchorDef(NodeFlags.None, null, null, 0)]))
|
||||||
|
]));
|
||||||
|
|
||||||
|
expect(instance.dep.createElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {CommonModule, PlatformLocation} from '@angular/common';
|
import {CommonModule, PlatformLocation} from '@angular/common';
|
||||||
import {ApplicationModule, ErrorHandler, NgModule, Optional, PLATFORM_INITIALIZER, PlatformRef, Provider, RENDERER_V2_DIRECT, RendererV2, RootRenderer, Sanitizer, SkipSelf, Testability, createPlatformFactory, platformCore} from '@angular/core';
|
import {ApplicationModule, ErrorHandler, NgModule, Optional, PLATFORM_INITIALIZER, PlatformRef, Provider, RendererFactoryV2, RootRenderer, Sanitizer, SkipSelf, Testability, createPlatformFactory, platformCore} from '@angular/core';
|
||||||
|
|
||||||
import {AnimationDriver} from '../src/dom/animation_driver';
|
import {AnimationDriver} from '../src/dom/animation_driver';
|
||||||
import {WebAnimationsDriver} from '../src/dom/web_animations_driver';
|
import {WebAnimationsDriver} from '../src/dom/web_animations_driver';
|
||||||
@ -19,7 +19,7 @@ import {BrowserGetTestability} from './browser/testability';
|
|||||||
import {Title} from './browser/title';
|
import {Title} from './browser/title';
|
||||||
import {ELEMENT_PROBE_PROVIDERS} from './dom/debug/ng_probe';
|
import {ELEMENT_PROBE_PROVIDERS} from './dom/debug/ng_probe';
|
||||||
import {getDOM} from './dom/dom_adapter';
|
import {getDOM} from './dom/dom_adapter';
|
||||||
import {DomRendererV2, DomRootRenderer, DomRootRenderer_} from './dom/dom_renderer';
|
import {DomRendererFactoryV2, DomRootRenderer, DomRootRenderer_} from './dom/dom_renderer';
|
||||||
import {DOCUMENT} from './dom/dom_tokens';
|
import {DOCUMENT} from './dom/dom_tokens';
|
||||||
import {DomEventsPlugin} from './dom/events/dom_events';
|
import {DomEventsPlugin} from './dom/events/dom_events';
|
||||||
import {EVENT_MANAGER_PLUGINS, EventManager} from './dom/events/event_manager';
|
import {EVENT_MANAGER_PLUGINS, EventManager} from './dom/events/event_manager';
|
||||||
@ -86,8 +86,8 @@ export function _resolveDefaultAnimationDriver(): AnimationDriver {
|
|||||||
{provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig},
|
{provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig},
|
||||||
{provide: DomRootRenderer, useClass: DomRootRenderer_},
|
{provide: DomRootRenderer, useClass: DomRootRenderer_},
|
||||||
{provide: RootRenderer, useExisting: DomRootRenderer},
|
{provide: RootRenderer, useExisting: DomRootRenderer},
|
||||||
{provide: RENDERER_V2_DIRECT, useClass: DomRendererV2},
|
DomRendererFactoryV2,
|
||||||
{provide: RendererV2, useExisting: RENDERER_V2_DIRECT},
|
{provide: RendererFactoryV2, useExisting: DomRendererFactoryV2},
|
||||||
{provide: SharedStylesHost, useExisting: DomSharedStylesHost},
|
{provide: SharedStylesHost, useExisting: DomSharedStylesHost},
|
||||||
{provide: AnimationDriver, useFactory: _resolveDefaultAnimationDriver},
|
{provide: AnimationDriver, useFactory: _resolveDefaultAnimationDriver},
|
||||||
DomSharedStylesHost,
|
DomSharedStylesHost,
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
import * as core from '@angular/core';
|
import * as core from '@angular/core';
|
||||||
|
|
||||||
import {StringMapWrapper} from '../../facade/collection';
|
import {StringMapWrapper} from '../../facade/collection';
|
||||||
import {DebugDomRendererV2, DebugDomRootRenderer} from '../../private_import_core';
|
import {DebugDomRootRenderer} from '../../private_import_core';
|
||||||
import {getDOM} from '../dom_adapter';
|
import {getDOM} from '../dom_adapter';
|
||||||
import {DomRootRenderer} from '../dom_renderer';
|
import {DomRendererFactoryV2, DomRootRenderer} from '../dom_renderer';
|
||||||
|
|
||||||
const CORE_TOKENS = {
|
const CORE_TOKENS = {
|
||||||
'ApplicationRef': core.ApplicationRef,
|
'ApplicationRef': core.ApplicationRef,
|
||||||
@ -58,10 +58,6 @@ function _ngProbeTokensToMap(tokens: NgProbeToken[]): {[name: string]: any} {
|
|||||||
return tokens.reduce((prev: any, t: any) => (prev[t.name] = t.token, prev), {});
|
return tokens.reduce((prev: any, t: any) => (prev[t.name] = t.token, prev), {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function _createDebugRendererV2(renderer: core.RendererV2): core.RendererV2 {
|
|
||||||
return core.isDevMode() ? new DebugDomRendererV2(renderer) : renderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Providers which support debugging Angular applications (e.g. via `ng.probe`).
|
* Providers which support debugging Angular applications (e.g. via `ng.probe`).
|
||||||
*/
|
*/
|
||||||
@ -75,9 +71,4 @@ export const ELEMENT_PROBE_PROVIDERS: core.Provider[] = [
|
|||||||
[core.NgProbeToken, new core.Optional()],
|
[core.NgProbeToken, new core.Optional()],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
provide: core.RendererV2,
|
|
||||||
useFactory: _createDebugRendererV2,
|
|
||||||
deps: [core.RENDERER_V2_DIRECT],
|
|
||||||
}
|
|
||||||
];
|
];
|
@ -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 {APP_ID, Inject, Injectable, RenderComponentType, Renderer, RendererV2, RootRenderer, ViewEncapsulation} from '@angular/core';
|
import {APP_ID, ComponentRenderTypeV2, Inject, Injectable, RenderComponentType, Renderer, RendererFactoryV2, RendererV2, RootRenderer, ViewEncapsulation} from '@angular/core';
|
||||||
|
|
||||||
import {isPresent, stringify} from '../facade/lang';
|
import {isPresent, stringify} from '../facade/lang';
|
||||||
import {AnimationKeyframe, AnimationPlayer, AnimationStyles, DirectRenderer, NoOpAnimationPlayer, RenderDebugInfo} from '../private_import_core';
|
import {AnimationKeyframe, AnimationPlayer, AnimationStyles, DirectRenderer, NoOpAnimationPlayer, RenderDebugInfo} from '../private_import_core';
|
||||||
@ -229,13 +229,8 @@ export class DomRenderer implements Renderer {
|
|||||||
TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(parsedBindings, null, 2));
|
TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(parsedBindings, null, 2));
|
||||||
} else {
|
} else {
|
||||||
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
||||||
if (propertyName[propertyName.length - 1] === '$') {
|
propertyName = propertyName.replace(/\$/g, '_');
|
||||||
const attrNode: Attr = createAttributeNode(propertyName).cloneNode(true) as Attr;
|
this.setElementAttribute(renderElement, propertyName, propertyValue);
|
||||||
attrNode.value = propertyValue;
|
|
||||||
renderElement.setAttributeNode(attrNode);
|
|
||||||
} else {
|
|
||||||
this.setElementAttribute(renderElement, propertyName, propertyValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,10 +361,51 @@ function createAttributeNode(name: string): Attr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DomRendererV2 implements RendererV2 {
|
export class DomRendererFactoryV2 implements RendererFactoryV2 {
|
||||||
constructor(private eventManager: EventManager){};
|
private rendererByCompId = new Map<string, RendererV2>();
|
||||||
|
private defaultRenderer: RendererV2;
|
||||||
|
|
||||||
createElement(name: string, namespace?: string, debugInfo?: any): any {
|
constructor(private eventManager: EventManager, private sharedStylesHost: DomSharedStylesHost) {
|
||||||
|
this.defaultRenderer = new DefaultDomRendererV2(eventManager);
|
||||||
|
};
|
||||||
|
|
||||||
|
createRenderer(element: any, type: ComponentRenderTypeV2): RendererV2 {
|
||||||
|
if (!element || !type) {
|
||||||
|
return this.defaultRenderer;
|
||||||
|
}
|
||||||
|
switch (type.encapsulation) {
|
||||||
|
case ViewEncapsulation.Emulated: {
|
||||||
|
let renderer = this.rendererByCompId.get(type.id);
|
||||||
|
if (!renderer) {
|
||||||
|
renderer = new EmulatedEncapsulationDomRendererV2(
|
||||||
|
this.eventManager, this.sharedStylesHost, type);
|
||||||
|
this.rendererByCompId.set(type.id, renderer);
|
||||||
|
}
|
||||||
|
(<EmulatedEncapsulationDomRendererV2>renderer).applyToHost(element);
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
case ViewEncapsulation.Native:
|
||||||
|
return new ShadowDomRenderer(this.eventManager, this.sharedStylesHost, element, type);
|
||||||
|
default: {
|
||||||
|
if (!this.rendererByCompId.has(type.id)) {
|
||||||
|
const styles = flattenStyles(type.id, type.styles, []);
|
||||||
|
this.sharedStylesHost.addStyles(styles);
|
||||||
|
this.rendererByCompId.set(type.id, this.defaultRenderer);
|
||||||
|
}
|
||||||
|
return this.defaultRenderer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultDomRendererV2 implements RendererV2 {
|
||||||
|
constructor(private eventManager: EventManager) {}
|
||||||
|
|
||||||
|
destroy(): void {}
|
||||||
|
|
||||||
|
destroyNode: null;
|
||||||
|
|
||||||
|
createElement(name: string, namespace?: string): any {
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
return document.createElementNS(NAMESPACE_URIS[namespace], name);
|
return document.createElementNS(NAMESPACE_URIS[namespace], name);
|
||||||
}
|
}
|
||||||
@ -377,9 +413,9 @@ export class DomRendererV2 implements RendererV2 {
|
|||||||
return document.createElement(name);
|
return document.createElement(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
createComment(value: string, debugInfo?: any): any { return document.createComment(value); }
|
createComment(value: string): any { return document.createComment(value); }
|
||||||
|
|
||||||
createText(value: string, debugInfo?: any): any { return document.createTextNode(value); }
|
createText(value: string): any { return document.createTextNode(value); }
|
||||||
|
|
||||||
appendChild(parent: any, newChild: any): void { parent.appendChild(newChild); }
|
appendChild(parent: any, newChild: any): void { parent.appendChild(newChild); }
|
||||||
|
|
||||||
@ -395,7 +431,7 @@ export class DomRendererV2 implements RendererV2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectRootElement(selectorOrNode: string|any, debugInfo?: any): any {
|
selectRootElement(selectorOrNode: string|any): any {
|
||||||
let el: any = typeof selectorOrNode === 'string' ? document.querySelector(selectorOrNode) :
|
let el: any = typeof selectorOrNode === 'string' ? document.querySelector(selectorOrNode) :
|
||||||
selectorOrNode;
|
selectorOrNode;
|
||||||
el.textContent = '';
|
el.textContent = '';
|
||||||
@ -422,43 +458,6 @@ export class DomRendererV2 implements RendererV2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setBindingDebugInfo(el: any, propertyName: string, propertyValue: string): void {
|
|
||||||
if (el.nodeType === Node.COMMENT_NODE) {
|
|
||||||
const m = el.nodeValue.replace(/\n/g, '').match(TEMPLATE_BINDINGS_EXP);
|
|
||||||
const obj = m === null ? {} : JSON.parse(m[1]);
|
|
||||||
obj[propertyName] = propertyValue;
|
|
||||||
el.nodeValue = TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(obj, null, 2));
|
|
||||||
} else {
|
|
||||||
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
|
||||||
if (propertyName[propertyName.length - 1] === '$') {
|
|
||||||
const attrNode: Attr = createAttributeNode(propertyName).cloneNode(true) as Attr;
|
|
||||||
attrNode.value = propertyValue;
|
|
||||||
el.setAttributeNode(attrNode);
|
|
||||||
} else {
|
|
||||||
this.setAttribute(el, propertyName, propertyValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeBindingDebugInfo(el: any, propertyName: string): void {
|
|
||||||
if (el.nodeType === Node.COMMENT_NODE) {
|
|
||||||
const m = el.nodeValue.replace(/\n/g, '').match(TEMPLATE_BINDINGS_EXP);
|
|
||||||
const obj = m === null ? {} : JSON.parse(m[1]);
|
|
||||||
delete obj[propertyName];
|
|
||||||
el.nodeValue = TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(obj, null, 2));
|
|
||||||
} else {
|
|
||||||
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
|
||||||
if (propertyName[propertyName.length - 1] === '$') {
|
|
||||||
const attrNode: Attr = createAttributeNode(propertyName).cloneNode(true) as Attr;
|
|
||||||
attrNode.value = '';
|
|
||||||
el.setAttributeNode(attrNode);
|
|
||||||
} else {
|
|
||||||
this.removeAttribute(el, propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addClass(el: any, name: string): void { el.classList.add(name); }
|
addClass(el: any, name: string): void { el.classList.add(name); }
|
||||||
|
|
||||||
removeClass(el: any, name: string): void { el.classList.remove(name); }
|
removeClass(el: any, name: string): void { el.classList.remove(name); }
|
||||||
@ -476,7 +475,7 @@ export class DomRendererV2 implements RendererV2 {
|
|||||||
|
|
||||||
setProperty(el: any, name: string, value: any): void { el[name] = value; }
|
setProperty(el: any, name: string, value: any): void { el[name] = value; }
|
||||||
|
|
||||||
setText(node: any, value: string): void { node.nodeValue = value; }
|
setValue(node: any, value: string): void { node.nodeValue = value; }
|
||||||
|
|
||||||
listen(target: 'window'|'document'|'body'|any, event: string, callback: (event: any) => boolean):
|
listen(target: 'window'|'document'|'body'|any, event: string, callback: (event: any) => boolean):
|
||||||
() => void {
|
() => void {
|
||||||
@ -488,3 +487,62 @@ export class DomRendererV2 implements RendererV2 {
|
|||||||
target, event, decoratePreventDefault(callback)) as() => void;
|
target, event, decoratePreventDefault(callback)) as() => void;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EmulatedEncapsulationDomRendererV2 extends DefaultDomRendererV2 {
|
||||||
|
private contentAttr: string;
|
||||||
|
private hostAttr: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
eventManager: EventManager, sharedStylesHost: DomSharedStylesHost,
|
||||||
|
private component: ComponentRenderTypeV2) {
|
||||||
|
super(eventManager);
|
||||||
|
const styles = flattenStyles(component.id, component.styles, []);
|
||||||
|
sharedStylesHost.addStyles(styles);
|
||||||
|
|
||||||
|
this.contentAttr = shimContentAttribute(component.id);
|
||||||
|
this.hostAttr = shimHostAttribute(component.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyToHost(element: any) { super.setAttribute(element, this.hostAttr, ''); }
|
||||||
|
|
||||||
|
createElement(parent: any, name: string): Element {
|
||||||
|
const el = super.createElement(parent, name);
|
||||||
|
super.setAttribute(el, this.contentAttr, '');
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShadowDomRenderer extends DefaultDomRendererV2 {
|
||||||
|
private shadowRoot: any;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
eventManager: EventManager, private sharedStylesHost: DomSharedStylesHost,
|
||||||
|
private hostEl: any, private component: ComponentRenderTypeV2) {
|
||||||
|
super(eventManager);
|
||||||
|
this.shadowRoot = (hostEl as any).createShadowRoot();
|
||||||
|
this.sharedStylesHost.addHost(this.shadowRoot);
|
||||||
|
const styles = flattenStyles(component.id, component.styles, []);
|
||||||
|
for (let i = 0; i < styles.length; i++) {
|
||||||
|
const styleEl = document.createElement('style');
|
||||||
|
styleEl.textContent = styles[i];
|
||||||
|
this.shadowRoot.appendChild(styleEl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private nodeOrShadowRoot(node: any): any { return node === this.hostEl ? this.shadowRoot : node; }
|
||||||
|
|
||||||
|
destroy() { this.sharedStylesHost.removeHost(this.shadowRoot); }
|
||||||
|
|
||||||
|
appendChild(parent: any, newChild: any): void {
|
||||||
|
return super.appendChild(this.nodeOrShadowRoot(parent), newChild);
|
||||||
|
}
|
||||||
|
insertBefore(parent: any, newChild: any, refChild: any): void {
|
||||||
|
return super.insertBefore(this.nodeOrShadowRoot(parent), newChild, refChild);
|
||||||
|
}
|
||||||
|
removeChild(parent: any, oldChild: any): void {
|
||||||
|
return super.removeChild(this.nodeOrShadowRoot(parent), oldChild);
|
||||||
|
}
|
||||||
|
parentNode(node: any): any {
|
||||||
|
return this.nodeOrShadowRoot(super.parentNode(this.nodeOrShadowRoot(node)));
|
||||||
|
}
|
||||||
|
}
|
@ -16,8 +16,6 @@ export const ReflectionCapabilities: typeof r.ReflectionCapabilities = r.Reflect
|
|||||||
|
|
||||||
export type DebugDomRootRenderer = typeof r._DebugDomRootRenderer;
|
export type DebugDomRootRenderer = typeof r._DebugDomRootRenderer;
|
||||||
export const DebugDomRootRenderer: typeof r.DebugDomRootRenderer = r.DebugDomRootRenderer;
|
export const DebugDomRootRenderer: typeof r.DebugDomRootRenderer = r.DebugDomRootRenderer;
|
||||||
export type DebugDomRendererV2 = typeof r._DebugDomRendererV2;
|
|
||||||
export const DebugDomRendererV2: typeof r.DebugDomRendererV2 = r.DebugDomRendererV2;
|
|
||||||
|
|
||||||
export const reflector: typeof r.reflector = r.reflector;
|
export const reflector: typeof r.reflector = r.reflector;
|
||||||
|
|
||||||
|
@ -21,8 +21,6 @@ export type RenderDebugInfo = typeof r._RenderDebugInfo;
|
|||||||
export const RenderDebugInfo: typeof r.RenderDebugInfo = r.RenderDebugInfo;
|
export const RenderDebugInfo: typeof r.RenderDebugInfo = r.RenderDebugInfo;
|
||||||
export type DebugDomRootRenderer = typeof r._DebugDomRootRenderer;
|
export type DebugDomRootRenderer = typeof r._DebugDomRootRenderer;
|
||||||
export const DebugDomRootRenderer: typeof r.DebugDomRootRenderer = r.DebugDomRootRenderer;
|
export const DebugDomRootRenderer: typeof r.DebugDomRootRenderer = r.DebugDomRootRenderer;
|
||||||
export type DebugDomRendererV2 = typeof r._DebugDomRendererV2;
|
|
||||||
export const DebugDomRendererV2: typeof r.DebugDomRendererV2 = r.DebugDomRendererV2;
|
|
||||||
export type ALLOW_MULTIPLE_PLATFORMS = typeof r.ALLOW_MULTIPLE_PLATFORMS;
|
export type ALLOW_MULTIPLE_PLATFORMS = typeof r.ALLOW_MULTIPLE_PLATFORMS;
|
||||||
export const ALLOW_MULTIPLE_PLATFORMS: typeof r.ALLOW_MULTIPLE_PLATFORMS =
|
export const ALLOW_MULTIPLE_PLATFORMS: typeof r.ALLOW_MULTIPLE_PLATFORMS =
|
||||||
r.ALLOW_MULTIPLE_PLATFORMS;
|
r.ALLOW_MULTIPLE_PLATFORMS;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import {PlatformLocation} from '@angular/common';
|
import {PlatformLocation} from '@angular/common';
|
||||||
import {platformCoreDynamic} from '@angular/compiler';
|
import {platformCoreDynamic} from '@angular/compiler';
|
||||||
import {APP_BOOTSTRAP_LISTENER, Injectable, InjectionToken, Injector, NgModule, PLATFORM_INITIALIZER, PlatformRef, Provider, RENDERER_V2_DIRECT, RendererV2, RootRenderer, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
|
import {APP_BOOTSTRAP_LISTENER, Injectable, InjectionToken, Injector, NgModule, PLATFORM_INITIALIZER, PlatformRef, Provider, RendererFactoryV2, RootRenderer, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
|
||||||
import {HttpModule} from '@angular/http';
|
import {HttpModule} from '@angular/http';
|
||||||
import {BrowserModule, DOCUMENT} from '@angular/platform-browser';
|
import {BrowserModule, DOCUMENT} from '@angular/platform-browser';
|
||||||
|
|
||||||
@ -16,9 +16,9 @@ import {SERVER_HTTP_PROVIDERS} from './http';
|
|||||||
import {ServerPlatformLocation} from './location';
|
import {ServerPlatformLocation} from './location';
|
||||||
import {Parse5DomAdapter, parseDocument} from './parse5_adapter';
|
import {Parse5DomAdapter, parseDocument} from './parse5_adapter';
|
||||||
import {PlatformState} from './platform_state';
|
import {PlatformState} from './platform_state';
|
||||||
import {ALLOW_MULTIPLE_PLATFORMS, DebugDomRendererV2, DebugDomRootRenderer} from './private_import_core';
|
import {ALLOW_MULTIPLE_PLATFORMS, DebugDomRootRenderer} from './private_import_core';
|
||||||
import {SharedStylesHost, getDOM} from './private_import_platform-browser';
|
import {SharedStylesHost, getDOM} from './private_import_platform-browser';
|
||||||
import {ServerRendererV2, ServerRootRenderer} from './server_renderer';
|
import {ServerRendererFactoryV2, ServerRootRenderer} from './server_renderer';
|
||||||
import {ServerStylesHost} from './styles_host';
|
import {ServerStylesHost} from './styles_host';
|
||||||
import {INITIAL_CONFIG, PlatformConfig} from './tokens';
|
import {INITIAL_CONFIG, PlatformConfig} from './tokens';
|
||||||
|
|
||||||
@ -42,10 +42,6 @@ export function _createConditionalRootRenderer(rootRenderer: any) {
|
|||||||
return isDevMode() ? new DebugDomRootRenderer(rootRenderer) : rootRenderer;
|
return isDevMode() ? new DebugDomRootRenderer(rootRenderer) : rootRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function _createDebugRendererV2(renderer: RendererV2): RendererV2 {
|
|
||||||
return isDevMode() ? new DebugDomRendererV2(renderer) : renderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function _addStylesToRootComponentFactory(stylesHost: ServerStylesHost) {
|
export function _addStylesToRootComponentFactory(stylesHost: ServerStylesHost) {
|
||||||
const initializer = () => stylesHost.rootComponentIsReady();
|
const initializer = () => stylesHost.rootComponentIsReady();
|
||||||
return initializer;
|
return initializer;
|
||||||
@ -53,9 +49,9 @@ export function _addStylesToRootComponentFactory(stylesHost: ServerStylesHost) {
|
|||||||
|
|
||||||
export const SERVER_RENDER_PROVIDERS: Provider[] = [
|
export const SERVER_RENDER_PROVIDERS: Provider[] = [
|
||||||
ServerRootRenderer,
|
ServerRootRenderer,
|
||||||
{provide: RENDERER_V2_DIRECT, useClass: ServerRendererV2},
|
|
||||||
{provide: RendererV2, useFactory: _createDebugRendererV2, deps: [RENDERER_V2_DIRECT]},
|
|
||||||
{provide: RootRenderer, useFactory: _createConditionalRootRenderer, deps: [ServerRootRenderer]},
|
{provide: RootRenderer, useFactory: _createConditionalRootRenderer, deps: [ServerRootRenderer]},
|
||||||
|
ServerRendererFactoryV2,
|
||||||
|
{provide: RendererFactoryV2, useExisting: ServerRendererFactoryV2},
|
||||||
ServerStylesHost,
|
ServerStylesHost,
|
||||||
{provide: SharedStylesHost, useExisting: ServerStylesHost},
|
{provide: SharedStylesHost, useExisting: ServerStylesHost},
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {DomElementSchemaRegistry} from '@angular/compiler';
|
import {DomElementSchemaRegistry} from '@angular/compiler';
|
||||||
import {APP_ID, Inject, Injectable, NgZone, RenderComponentType, Renderer, RendererV2, RootRenderer, ViewEncapsulation} from '@angular/core';
|
import {APP_ID, ComponentRenderTypeV2, Inject, Injectable, NgZone, RenderComponentType, Renderer, RendererFactoryV2, RendererV2, RootRenderer, ViewEncapsulation} from '@angular/core';
|
||||||
import {AnimationDriver, DOCUMENT} from '@angular/platform-browser';
|
import {AnimationDriver, DOCUMENT} from '@angular/platform-browser';
|
||||||
|
|
||||||
import {isBlank, isPresent, stringify} from './facade/lang';
|
import {isBlank, isPresent, stringify} from './facade/lang';
|
||||||
@ -204,6 +204,7 @@ export class ServerRenderer implements Renderer {
|
|||||||
renderElement,
|
renderElement,
|
||||||
TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(parsedBindings, null, 2)));
|
TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(parsedBindings, null, 2)));
|
||||||
} else {
|
} else {
|
||||||
|
propertyName = propertyName.replace(/\$/g, '_');
|
||||||
this.setElementAttribute(renderElement, propertyName, propertyValue);
|
this.setElementAttribute(renderElement, propertyName, propertyValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,8 +263,51 @@ function appendNodes(parent: any, nodes: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ServerRendererV2 implements RendererV2 {
|
export class ServerRendererFactoryV2 implements RendererFactoryV2 {
|
||||||
constructor(private ngZone: NgZone, @Inject(DOCUMENT) private document: any) {}
|
private rendererByCompId = new Map<string, RendererV2>();
|
||||||
|
private defaultRenderer: RendererV2;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private ngZone: NgZone, @Inject(DOCUMENT) private document: any,
|
||||||
|
private sharedStylesHost: SharedStylesHost) {
|
||||||
|
this.defaultRenderer = new DefaultServerRendererV2(document, ngZone);
|
||||||
|
};
|
||||||
|
|
||||||
|
createRenderer(element: any, type: ComponentRenderTypeV2): RendererV2 {
|
||||||
|
if (!element || !type) {
|
||||||
|
return this.defaultRenderer;
|
||||||
|
}
|
||||||
|
switch (type.encapsulation) {
|
||||||
|
case ViewEncapsulation.Emulated: {
|
||||||
|
let renderer = this.rendererByCompId.get(type.id);
|
||||||
|
if (!renderer) {
|
||||||
|
renderer = new EmulatedEncapsulationServerRendererV2(
|
||||||
|
this.document, this.ngZone, this.sharedStylesHost, type);
|
||||||
|
this.rendererByCompId.set(type.id, renderer);
|
||||||
|
}
|
||||||
|
(<EmulatedEncapsulationServerRendererV2>renderer).applyToHost(element);
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
case ViewEncapsulation.Native:
|
||||||
|
throw new Error('Native encapsulation is not supported on the server!');
|
||||||
|
default: {
|
||||||
|
if (!this.rendererByCompId.has(type.id)) {
|
||||||
|
const styles = flattenStyles(type.id, type.styles, []);
|
||||||
|
this.sharedStylesHost.addStyles(styles);
|
||||||
|
this.rendererByCompId.set(type.id, this.defaultRenderer);
|
||||||
|
}
|
||||||
|
return this.defaultRenderer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultServerRendererV2 implements RendererV2 {
|
||||||
|
constructor(private document: any, private ngZone: NgZone) {}
|
||||||
|
|
||||||
|
destroy(): void {}
|
||||||
|
|
||||||
|
destroyNode: null;
|
||||||
|
|
||||||
createElement(name: string, namespace?: string, debugInfo?: any): any {
|
createElement(name: string, namespace?: string, debugInfo?: any): any {
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
@ -325,28 +369,6 @@ export class ServerRendererV2 implements RendererV2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setBindingDebugInfo(el: any, propertyName: string, propertyValue: string): void {
|
|
||||||
if (getDOM().isCommentNode(el)) {
|
|
||||||
const m = getDOM().getText(el).replace(/\n/g, '').match(TEMPLATE_BINDINGS_EXP);
|
|
||||||
const obj = m === null ? {} : JSON.parse(m[1]);
|
|
||||||
obj[propertyName] = propertyValue;
|
|
||||||
getDOM().setText(el, TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(obj, null, 2)));
|
|
||||||
} else {
|
|
||||||
this.setAttribute(el, propertyName, propertyValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeBindingDebugInfo(el: any, propertyName: string): void {
|
|
||||||
if (getDOM().isCommentNode(el)) {
|
|
||||||
const m = getDOM().getText(el).replace(/\n/g, '').match(TEMPLATE_BINDINGS_EXP);
|
|
||||||
const obj = m === null ? {} : JSON.parse(m[1]);
|
|
||||||
delete obj[propertyName];
|
|
||||||
getDOM().setText(el, TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(obj, null, 2)));
|
|
||||||
} else {
|
|
||||||
this.removeAttribute(el, propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addClass(el: any, name: string): void { getDOM().addClass(el, name); }
|
addClass(el: any, name: string): void { getDOM().addClass(el, name); }
|
||||||
|
|
||||||
removeClass(el: any, name: string): void { getDOM().removeClass(el, name); }
|
removeClass(el: any, name: string): void { getDOM().removeClass(el, name); }
|
||||||
@ -362,7 +384,7 @@ export class ServerRendererV2 implements RendererV2 {
|
|||||||
|
|
||||||
setProperty(el: any, name: string, value: any): void { getDOM().setProperty(el, name, value); }
|
setProperty(el: any, name: string, value: any): void { getDOM().setProperty(el, name, value); }
|
||||||
|
|
||||||
setText(node: any, value: string): void { getDOM().setText(node, value); }
|
setValue(node: any, value: string): void { getDOM().setText(node, value); }
|
||||||
|
|
||||||
listen(
|
listen(
|
||||||
target: 'document'|'window'|'body'|any, eventName: string,
|
target: 'document'|'window'|'body'|any, eventName: string,
|
||||||
@ -375,3 +397,27 @@ export class ServerRendererV2 implements RendererV2 {
|
|||||||
return this.ngZone.runOutsideAngular(() => getDOM().onAndCancel(el, eventName, outsideHandler));
|
return this.ngZone.runOutsideAngular(() => getDOM().onAndCancel(el, eventName, outsideHandler));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EmulatedEncapsulationServerRendererV2 extends DefaultServerRendererV2 {
|
||||||
|
private contentAttr: string;
|
||||||
|
private hostAttr: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
document: any, ngZone: NgZone, sharedStylesHost: SharedStylesHost,
|
||||||
|
private component: ComponentRenderTypeV2) {
|
||||||
|
super(document, ngZone);
|
||||||
|
const styles = flattenStyles(component.id, component.styles, []);
|
||||||
|
sharedStylesHost.addStyles(styles);
|
||||||
|
|
||||||
|
this.contentAttr = shimContentAttribute(component.id);
|
||||||
|
this.hostAttr = shimHostAttribute(component.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyToHost(element: any) { super.setAttribute(element, this.hostAttr, ''); }
|
||||||
|
|
||||||
|
createElement(parent: any, name: string): Element {
|
||||||
|
const el = super.createElement(parent, name);
|
||||||
|
super.setAttribute(el, this.contentAttr, '');
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {NgIf} from '@angular/common';
|
import {NgIf} from '@angular/common';
|
||||||
import {ComponentFactory, ComponentRef, Injector, RendererV2, RootRenderer, Sanitizer, TemplateRef, ViewContainerRef} from '@angular/core';
|
import {ComponentFactory, ComponentRef, Injector, RendererFactoryV2, RootRenderer, Sanitizer, TemplateRef, ViewContainerRef} from '@angular/core';
|
||||||
import {ArgumentType, BindingType, NodeFlags, ViewDefinition, ViewFlags, anchorDef, createComponentFactory, directiveDef, elementDef, initServicesIfNeeded, textDef, viewDef} from '@angular/core/src/view/index';
|
import {ArgumentType, BindingType, NodeFlags, ViewDefinition, ViewFlags, anchorDef, createComponentFactory, directiveDef, elementDef, initServicesIfNeeded, textDef, viewDef} from '@angular/core/src/view/index';
|
||||||
import {DomRendererV2} from '@angular/platform-browser/src/dom/dom_renderer';
|
import {DomRendererFactoryV2} from '@angular/platform-browser/src/dom/dom_renderer';
|
||||||
import {DomSanitizerImpl, SafeStyle} from '@angular/platform-browser/src/security/dom_sanitization_service';
|
import {DomSanitizerImpl, SafeStyle} from '@angular/platform-browser/src/security/dom_sanitization_service';
|
||||||
|
|
||||||
import {TreeNode, emptyTree} from '../util';
|
import {TreeNode, emptyTree} from '../util';
|
||||||
@ -89,14 +89,14 @@ function TreeComponent_0(): ViewDefinition {
|
|||||||
export class AppModule implements Injector {
|
export class AppModule implements Injector {
|
||||||
private sanitizer: DomSanitizerImpl;
|
private sanitizer: DomSanitizerImpl;
|
||||||
private componentFactory: ComponentFactory<TreeComponent>;
|
private componentFactory: ComponentFactory<TreeComponent>;
|
||||||
private rendererV2: RendererV2;
|
private rendererV2: RendererFactoryV2;
|
||||||
|
|
||||||
componentRef: ComponentRef<TreeComponent>;
|
componentRef: ComponentRef<TreeComponent>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
initServicesIfNeeded();
|
initServicesIfNeeded();
|
||||||
this.sanitizer = new DomSanitizerImpl(document);
|
this.sanitizer = new DomSanitizerImpl(document);
|
||||||
this.rendererV2 = new DomRendererV2(null);
|
this.rendererV2 = new DomRendererFactoryV2(null, null);
|
||||||
trustedEmptyColor = this.sanitizer.bypassSecurityTrustStyle('');
|
trustedEmptyColor = this.sanitizer.bypassSecurityTrustStyle('');
|
||||||
trustedGreyColor = this.sanitizer.bypassSecurityTrustStyle('grey');
|
trustedGreyColor = this.sanitizer.bypassSecurityTrustStyle('grey');
|
||||||
this.componentFactory = createComponentFactory('#root', TreeComponent, TreeComponent_Host);
|
this.componentFactory = createComponentFactory('#root', TreeComponent, TreeComponent_Host);
|
||||||
@ -104,7 +104,7 @@ export class AppModule implements Injector {
|
|||||||
|
|
||||||
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
|
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case RendererV2:
|
case RendererFactoryV2:
|
||||||
return this.rendererV2;
|
return this.rendererV2;
|
||||||
case Sanitizer:
|
case Sanitizer:
|
||||||
return this.sanitizer;
|
return this.sanitizer;
|
||||||
|
28
tools/public_api_guard/core/index.d.ts
vendored
28
tools/public_api_guard/core/index.d.ts
vendored
@ -292,6 +292,16 @@ export declare abstract class ComponentRef<C> {
|
|||||||
abstract onDestroy(callback: Function): void;
|
abstract onDestroy(callback: Function): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @experimental */
|
||||||
|
export interface ComponentRenderTypeV2 {
|
||||||
|
data: {
|
||||||
|
[kind: string]: any[];
|
||||||
|
};
|
||||||
|
encapsulation: ViewEncapsulation;
|
||||||
|
id: string;
|
||||||
|
styles: (string | any[])[];
|
||||||
|
}
|
||||||
|
|
||||||
/** @stable */
|
/** @stable */
|
||||||
export declare const ContentChild: ContentChildDecorator;
|
export declare const ContentChild: ContentChildDecorator;
|
||||||
|
|
||||||
@ -848,30 +858,32 @@ export declare abstract class Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare const RENDERER_V2_DIRECT: InjectionToken<RendererV2>;
|
export declare abstract class RendererFactoryV2 {
|
||||||
|
abstract createRenderer(hostElement: any, type: ComponentRenderTypeV2): RendererV2;
|
||||||
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare abstract class RendererV2 {
|
export declare abstract class RendererV2 {
|
||||||
|
destroyNode: (node: any) => void | null;
|
||||||
abstract addClass(el: any, name: string): void;
|
abstract addClass(el: any, name: string): void;
|
||||||
abstract appendChild(parent: any, newChild: any): void;
|
abstract appendChild(parent: any, newChild: any): void;
|
||||||
abstract createComment(value: string, debugInfo?: RenderDebugContext): any;
|
abstract createComment(value: string): any;
|
||||||
abstract createElement(name: string, namespace?: string, debugInfo?: RenderDebugContext): any;
|
abstract createElement(name: string, namespace?: string): any;
|
||||||
abstract createText(value: string, debugInfo?: RenderDebugContext): any;
|
abstract createText(value: string): any;
|
||||||
|
abstract destroy(): void;
|
||||||
abstract insertBefore(parent: any, newChild: any, refChild: any): void;
|
abstract insertBefore(parent: any, newChild: any, refChild: any): void;
|
||||||
abstract listen(target: 'window' | 'document' | 'body' | any, eventName: string, callback: (event: any) => boolean): () => void;
|
abstract listen(target: 'window' | 'document' | 'body' | any, eventName: string, callback: (event: any) => boolean): () => void;
|
||||||
abstract nextSibling(node: any): any;
|
abstract nextSibling(node: any): any;
|
||||||
abstract parentNode(node: any): any;
|
abstract parentNode(node: any): any;
|
||||||
abstract removeAttribute(el: any, name: string, namespace?: string): void;
|
abstract removeAttribute(el: any, name: string, namespace?: string): void;
|
||||||
abstract removeBindingDebugInfo(el: any, propertyName: string): void;
|
|
||||||
abstract removeChild(parent: any, oldChild: any): void;
|
abstract removeChild(parent: any, oldChild: any): void;
|
||||||
abstract removeClass(el: any, name: string): void;
|
abstract removeClass(el: any, name: string): void;
|
||||||
abstract removeStyle(el: any, style: string, hasVendorPrefix: boolean): void;
|
abstract removeStyle(el: any, style: string, hasVendorPrefix: boolean): void;
|
||||||
abstract selectRootElement(selectorOrNode: string | any, debugInfo?: RenderDebugContext): any;
|
abstract selectRootElement(selectorOrNode: string | any): any;
|
||||||
abstract setAttribute(el: any, name: string, value: string, namespace?: string): void;
|
abstract setAttribute(el: any, name: string, value: string, namespace?: string): void;
|
||||||
abstract setBindingDebugInfo(el: any, propertyName: string, propertyValue: string): void;
|
|
||||||
abstract setProperty(el: any, name: string, value: any): void;
|
abstract setProperty(el: any, name: string, value: any): void;
|
||||||
abstract setStyle(el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean): void;
|
abstract setStyle(el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean): void;
|
||||||
abstract setText(node: any, value: string): void;
|
abstract setValue(node: any, value: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user