refactor(compiler): various cleanups
- use `$implicit` variable value correctly - handle `ng-non-bindable` correctly - add some more assertions to `TemplateCompiler` - make `CompiledTemplate` const - fix default value for `@Directive.moduleId` - add new compiler to application bindings BREAKING CHANGE: - `Compiler.compileInHost` and all methods of `DynamicComponentLoader` don’t take `Binding` any more, only `Type`s. This is in preparation for the new compiler which does not support this. Part of #3605 Closes #4346
This commit is contained in:
@ -129,9 +129,7 @@ export class Compiler {
|
||||
|
||||
// Create a hostView as if the compiler encountered <hostcmp></hostcmp>.
|
||||
// Used for bootstrapping.
|
||||
compileInHost(componentTypeOrBinding: Type | Binding): Promise<ProtoViewRef> {
|
||||
var componentType = isType(componentTypeOrBinding) ? componentTypeOrBinding :
|
||||
(<Binding>componentTypeOrBinding).token;
|
||||
compileInHost(componentType: Type): Promise<ProtoViewRef> {
|
||||
var r = wtfStartTimeRange('Compiler#compile()', stringify(componentType));
|
||||
|
||||
var hostAppProtoView = this._compilerCache.getHost(componentType);
|
||||
@ -139,7 +137,7 @@ export class Compiler {
|
||||
if (isPresent(hostAppProtoView)) {
|
||||
hostPvPromise = PromiseWrapper.resolve(hostAppProtoView);
|
||||
} else {
|
||||
var componentBinding: DirectiveBinding = this._bindDirective(componentTypeOrBinding);
|
||||
var componentBinding: DirectiveBinding = this._bindDirective(componentType);
|
||||
Compiler._assertTypeIsComponent(componentBinding);
|
||||
|
||||
var directiveMetadata = componentBinding.metadata;
|
||||
|
@ -6,10 +6,6 @@ import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
||||
import {ElementRef} from './element_ref';
|
||||
import {ViewRef, HostViewRef} from './view_ref';
|
||||
|
||||
function _asType(typeOrBinding: Type | Binding): Type {
|
||||
return isType(typeOrBinding) ? typeOrBinding : (<Binding>typeOrBinding).token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Angular's reference to a component instance.
|
||||
*
|
||||
@ -69,7 +65,7 @@ export class DynamicComponentLoader {
|
||||
* Loads a root component that is placed at the first element that matches the component's
|
||||
* selector.
|
||||
*
|
||||
* - `typeOrBinding` `Type` \ {@link Binding} - representing the component to load.
|
||||
* - `typeOrBinding` `Type` - representing the component to load.
|
||||
* - `overrideSelector` (optional) selector to load the component at (or use
|
||||
* `@Component.selector`) The selector can be anywhere (i.e. outside the current component.)
|
||||
* - `injector` {@link Injector} - optional injector to use for the component.
|
||||
@ -120,24 +116,22 @@ export class DynamicComponentLoader {
|
||||
* </my-app>
|
||||
* ```
|
||||
*/
|
||||
loadAsRoot(typeOrBinding: Type | Binding, overrideSelector: string, injector: Injector,
|
||||
loadAsRoot(type: Type, overrideSelector: string, injector: Injector,
|
||||
onDispose?: () => void): Promise<ComponentRef> {
|
||||
return this._compiler.compileInHost(typeOrBinding)
|
||||
.then(hostProtoViewRef => {
|
||||
var hostViewRef =
|
||||
this._viewManager.createRootHostView(hostProtoViewRef, overrideSelector, injector);
|
||||
var newLocation = this._viewManager.getHostElement(hostViewRef);
|
||||
var component = this._viewManager.getComponent(newLocation);
|
||||
return this._compiler.compileInHost(type).then(hostProtoViewRef => {
|
||||
var hostViewRef =
|
||||
this._viewManager.createRootHostView(hostProtoViewRef, overrideSelector, injector);
|
||||
var newLocation = this._viewManager.getHostElement(hostViewRef);
|
||||
var component = this._viewManager.getComponent(newLocation);
|
||||
|
||||
var dispose = () => {
|
||||
this._viewManager.destroyRootHostView(hostViewRef);
|
||||
if (isPresent(onDispose)) {
|
||||
onDispose();
|
||||
}
|
||||
};
|
||||
return new ComponentRef(newLocation, component, _asType(typeOrBinding), injector,
|
||||
dispose);
|
||||
});
|
||||
var dispose = () => {
|
||||
this._viewManager.destroyRootHostView(hostViewRef);
|
||||
if (isPresent(onDispose)) {
|
||||
onDispose();
|
||||
}
|
||||
};
|
||||
return new ComponentRef(newLocation, component, type, injector, dispose);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,11 +181,10 @@ export class DynamicComponentLoader {
|
||||
* </my-app>
|
||||
* ```
|
||||
*/
|
||||
loadIntoLocation(typeOrBinding: Type | Binding, hostLocation: ElementRef, anchorName: string,
|
||||
loadIntoLocation(type: Type, hostLocation: ElementRef, anchorName: string,
|
||||
bindings: ResolvedBinding[] = null): Promise<ComponentRef> {
|
||||
return this.loadNextToLocation(
|
||||
typeOrBinding, this._viewManager.getNamedElementInComponentView(hostLocation, anchorName),
|
||||
bindings);
|
||||
type, this._viewManager.getNamedElementInComponentView(hostLocation, anchorName), bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -235,23 +228,22 @@ export class DynamicComponentLoader {
|
||||
* <child-component>Child</child-component>
|
||||
* ```
|
||||
*/
|
||||
loadNextToLocation(typeOrBinding: Type | Binding, location: ElementRef,
|
||||
loadNextToLocation(type: Type, location: ElementRef,
|
||||
bindings: ResolvedBinding[] = null): Promise<ComponentRef> {
|
||||
return this._compiler.compileInHost(typeOrBinding)
|
||||
.then(hostProtoViewRef => {
|
||||
var viewContainer = this._viewManager.getViewContainer(location);
|
||||
var hostViewRef =
|
||||
viewContainer.createHostView(hostProtoViewRef, viewContainer.length, bindings);
|
||||
var newLocation = this._viewManager.getHostElement(hostViewRef);
|
||||
var component = this._viewManager.getComponent(newLocation);
|
||||
return this._compiler.compileInHost(type).then(hostProtoViewRef => {
|
||||
var viewContainer = this._viewManager.getViewContainer(location);
|
||||
var hostViewRef =
|
||||
viewContainer.createHostView(hostProtoViewRef, viewContainer.length, bindings);
|
||||
var newLocation = this._viewManager.getHostElement(hostViewRef);
|
||||
var component = this._viewManager.getComponent(newLocation);
|
||||
|
||||
var dispose = () => {
|
||||
var index = viewContainer.indexOf(<ViewRef>hostViewRef);
|
||||
if (index !== -1) {
|
||||
viewContainer.remove(index);
|
||||
}
|
||||
};
|
||||
return new ComponentRef(newLocation, component, _asType(typeOrBinding), null, dispose);
|
||||
});
|
||||
var dispose = () => {
|
||||
var index = viewContainer.indexOf(<ViewRef>hostViewRef);
|
||||
if (index !== -1) {
|
||||
viewContainer.remove(index);
|
||||
}
|
||||
};
|
||||
return new ComponentRef(newLocation, component, type, null, dispose);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Type, CONST_EXPR, isPresent, isBlank} from 'angular2/src/core/facade/lang';
|
||||
import {Type, CONST_EXPR, CONST, isPresent, isBlank} from 'angular2/src/core/facade/lang';
|
||||
import {
|
||||
RenderTemplateCmd,
|
||||
RenderCommandVisitor,
|
||||
@ -9,47 +9,32 @@ import {
|
||||
RenderEmbeddedTemplateCmd
|
||||
} from 'angular2/src/core/render/render';
|
||||
|
||||
/**
|
||||
* A compiled template. This is const as we are storing it as annotation
|
||||
* for the compiled component type.
|
||||
*/
|
||||
@CONST()
|
||||
export class CompiledTemplate {
|
||||
private _changeDetectorFactory: Function = null;
|
||||
private _styles: string[] = null;
|
||||
private _commands: TemplateCmd[] = null;
|
||||
// Note: paramGetter is a function so that we can have cycles between templates!
|
||||
constructor(public id: number, private _paramGetter: Function) {}
|
||||
|
||||
private _init() {
|
||||
if (isBlank(this._commands)) {
|
||||
var params = this._paramGetter();
|
||||
this._changeDetectorFactory = params[0];
|
||||
this._commands = params[1];
|
||||
this._styles = params[2];
|
||||
}
|
||||
}
|
||||
|
||||
get changeDetectorFactory(): Function {
|
||||
this._init();
|
||||
return this._changeDetectorFactory;
|
||||
}
|
||||
|
||||
get styles(): string[] {
|
||||
this._init();
|
||||
return this._styles;
|
||||
}
|
||||
|
||||
get commands(): TemplateCmd[] {
|
||||
this._init();
|
||||
return this._commands;
|
||||
}
|
||||
// paramGetter returns a tuple with:
|
||||
// - ChangeDetector factory function
|
||||
// - TemplateCmd[]
|
||||
// - styles
|
||||
constructor(public id: number,
|
||||
public dataGetter: /*()=>[Function, TemplateCmd[], string[]]*/ Function) {}
|
||||
}
|
||||
|
||||
const EMPTY_ARR = CONST_EXPR([]);
|
||||
|
||||
export interface TemplateCmd extends RenderTemplateCmd {
|
||||
visit(visitor: CommandVisitor, context: any): any;
|
||||
visit(visitor: RenderCommandVisitor, context: any): any;
|
||||
}
|
||||
|
||||
export class TextCmd implements TemplateCmd, RenderTextCmd {
|
||||
constructor(public value: string, public isBound: boolean, public ngContentIndex: number) {}
|
||||
visit(visitor: CommandVisitor, context: any): any { return visitor.visitText(this, context); }
|
||||
visit(visitor: RenderCommandVisitor, context: any): any {
|
||||
return visitor.visitText(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export function text(value: string, isBound: boolean, ngContentIndex: number): TextCmd {
|
||||
@ -59,7 +44,7 @@ export function text(value: string, isBound: boolean, ngContentIndex: number): T
|
||||
export class NgContentCmd implements TemplateCmd, RenderNgContentCmd {
|
||||
isBound: boolean = false;
|
||||
constructor(public ngContentIndex: number) {}
|
||||
visit(visitor: CommandVisitor, context: any): any {
|
||||
visit(visitor: RenderCommandVisitor, context: any): any {
|
||||
return visitor.visitNgContent(this, context);
|
||||
}
|
||||
}
|
||||
@ -72,7 +57,7 @@ export interface IBeginElementCmd extends TemplateCmd, RenderBeginElementCmd {
|
||||
variableNameAndValues: Array<string | number>;
|
||||
eventTargetAndNames: string[];
|
||||
directives: Type[];
|
||||
visit(visitor: CommandVisitor, context: any): any;
|
||||
visit(visitor: RenderCommandVisitor, context: any): any;
|
||||
}
|
||||
|
||||
export class BeginElementCmd implements TemplateCmd, IBeginElementCmd, RenderBeginElementCmd {
|
||||
@ -80,7 +65,7 @@ export class BeginElementCmd implements TemplateCmd, IBeginElementCmd, RenderBeg
|
||||
public eventTargetAndNames: string[],
|
||||
public variableNameAndValues: Array<string | number>, public directives: Type[],
|
||||
public isBound: boolean, public ngContentIndex: number) {}
|
||||
visit(visitor: CommandVisitor, context: any): any {
|
||||
visit(visitor: RenderCommandVisitor, context: any): any {
|
||||
return visitor.visitBeginElement(this, context);
|
||||
}
|
||||
}
|
||||
@ -94,7 +79,9 @@ export function beginElement(name: string, attrNameAndValues: string[],
|
||||
}
|
||||
|
||||
export class EndElementCmd implements TemplateCmd {
|
||||
visit(visitor: CommandVisitor, context: any): any { return visitor.visitEndElement(context); }
|
||||
visit(visitor: RenderCommandVisitor, context: any): any {
|
||||
return visitor.visitEndElement(context);
|
||||
}
|
||||
}
|
||||
|
||||
export function endElement(): TemplateCmd {
|
||||
@ -113,7 +100,7 @@ export class BeginComponentCmd implements TemplateCmd, IBeginElementCmd, RenderB
|
||||
this.component = directives[0];
|
||||
this.templateId = template.id;
|
||||
}
|
||||
visit(visitor: CommandVisitor, context: any): any {
|
||||
visit(visitor: RenderCommandVisitor, context: any): any {
|
||||
return visitor.visitBeginComponent(this, context);
|
||||
}
|
||||
}
|
||||
@ -127,7 +114,9 @@ export function beginComponent(
|
||||
}
|
||||
|
||||
export class EndComponentCmd implements TemplateCmd {
|
||||
visit(visitor: CommandVisitor, context: any): any { return visitor.visitEndComponent(context); }
|
||||
visit(visitor: RenderCommandVisitor, context: any): any {
|
||||
return visitor.visitEndComponent(context);
|
||||
}
|
||||
}
|
||||
|
||||
export function endComponent(): TemplateCmd {
|
||||
@ -142,7 +131,7 @@ export class EmbeddedTemplateCmd implements TemplateCmd, IBeginElementCmd,
|
||||
constructor(public attrNameAndValues: string[], public variableNameAndValues: string[],
|
||||
public directives: Type[], public isMerged: boolean, public ngContentIndex: number,
|
||||
public changeDetectorFactory: Function, public children: TemplateCmd[]) {}
|
||||
visit(visitor: CommandVisitor, context: any): any {
|
||||
visit(visitor: RenderCommandVisitor, context: any): any {
|
||||
return visitor.visitEmbeddedTemplate(this, context);
|
||||
}
|
||||
}
|
||||
@ -155,7 +144,15 @@ export function embeddedTemplate(attrNameAndValues: string[], variableNameAndVal
|
||||
ngContentIndex, changeDetectorFactory, children);
|
||||
}
|
||||
|
||||
export interface CommandVisitor extends RenderCommandVisitor {}
|
||||
export interface CommandVisitor extends RenderCommandVisitor {
|
||||
visitText(cmd: TextCmd, context: any): any;
|
||||
visitNgContent(cmd: NgContentCmd, context: any): any;
|
||||
visitBeginElement(cmd: BeginElementCmd, context: any): any;
|
||||
visitEndElement(context: any): any;
|
||||
visitBeginComponent(cmd: BeginComponentCmd, context: any): any;
|
||||
visitEndComponent(context: any): any;
|
||||
visitEmbeddedTemplate(cmd: EmbeddedTemplateCmd, context: any): any;
|
||||
}
|
||||
|
||||
export function visitAllCommands(visitor: CommandVisitor, cmds: TemplateCmd[],
|
||||
context: any = null) {
|
||||
|
Reference in New Issue
Block a user