refactor(shadow dom): do not use injectors nor directives

This prepares us for the app/render split in the compiler.
This commit is contained in:
Yegor Jbanov 2015-03-16 11:31:58 -07:00
parent 115ac5f290
commit 70c875ee14
31 changed files with 367 additions and 343 deletions

View File

@ -67,7 +67,7 @@ function _injectorBindings(appComponentType): List<Binding> {
// the angular application. Thus the context and lightDomInjector are // the angular application. Thus the context and lightDomInjector are
// empty. // empty.
var view = appProtoView.instantiate(null, eventManager); var view = appProtoView.instantiate(null, eventManager);
view.hydrate(injector, null, new Object()); view.hydrate(injector, null, null, new Object());
return view; return view;
}); });
}, [ChangeDetection, Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken, }, [ChangeDetection, Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken,

View File

@ -11,7 +11,6 @@ import {CompileElement} from './pipeline/compile_element';
import {createDefaultSteps} from './pipeline/default_steps'; import {createDefaultSteps} from './pipeline/default_steps';
import {TemplateLoader} from './template_loader'; import {TemplateLoader} from './template_loader';
import {TemplateResolver} from './template_resolver'; import {TemplateResolver} from './template_resolver';
import {DirectiveMetadata} from './directive_metadata';
import {Template} from '../annotations/template'; import {Template} from '../annotations/template';
import {ShadowDomStrategy} from './shadow_dom_strategy'; import {ShadowDomStrategy} from './shadow_dom_strategy';
import {CompileStep} from './pipeline/compile_step'; import {CompileStep} from './pipeline/compile_step';
@ -56,7 +55,6 @@ export class Compiler {
_templateLoader:TemplateLoader; _templateLoader:TemplateLoader;
_compiling:Map<Type, Promise>; _compiling:Map<Type, Promise>;
_shadowDomStrategy: ShadowDomStrategy; _shadowDomStrategy: ShadowDomStrategy;
_shadowDomDirectives: List<DirectiveMetadata>;
_templateResolver: TemplateResolver; _templateResolver: TemplateResolver;
_componentUrlMapper: ComponentUrlMapper; _componentUrlMapper: ComponentUrlMapper;
_urlResolver: UrlResolver; _urlResolver: UrlResolver;
@ -80,11 +78,6 @@ export class Compiler {
this._templateLoader = templateLoader; this._templateLoader = templateLoader;
this._compiling = MapWrapper.create(); this._compiling = MapWrapper.create();
this._shadowDomStrategy = shadowDomStrategy; this._shadowDomStrategy = shadowDomStrategy;
this._shadowDomDirectives = [];
var types = shadowDomStrategy.polyfillDirectives();
for (var i = 0; i < types.length; i++) {
ListWrapper.push(this._shadowDomDirectives, reader.read(types[i]));
}
this._templateResolver = templateResolver; this._templateResolver = templateResolver;
this._componentUrlMapper = componentUrlMapper; this._componentUrlMapper = componentUrlMapper;
this._urlResolver = urlResolver; this._urlResolver = urlResolver;
@ -93,12 +86,8 @@ export class Compiler {
} }
createSteps(component:Type, template: Template):List<CompileStep> { createSteps(component:Type, template: Template):List<CompileStep> {
// Merge directive metadata (from the template and from the shadow dom strategy) var dirMetadata = ListWrapper.map(this._flattenDirectives(template),
var dirMetadata = [];
var tplMetadata = ListWrapper.map(this._flattenDirectives(template),
(d) => this._reader.read(d)); (d) => this._reader.read(d));
dirMetadata = ListWrapper.concat(dirMetadata, tplMetadata);
dirMetadata = ListWrapper.concat(dirMetadata, this._shadowDomDirectives);
var cmpMetadata = this._reader.read(component); var cmpMetadata = this._reader.read(component);

View File

@ -1,3 +1,4 @@
import {int, isBlank, BaseException} from 'angular2/src/facade/lang';
import {ProtoElementInjector} from './element_injector'; import {ProtoElementInjector} from './element_injector';
import {DirectiveMetadata} from './directive_metadata'; import {DirectiveMetadata} from './directive_metadata';
import {List, StringMap} from 'angular2/src/facade/collection'; import {List, StringMap} from 'angular2/src/facade/collection';
@ -11,12 +12,24 @@ export class ElementBinder {
hasElementPropertyBindings:boolean; hasElementPropertyBindings:boolean;
nestedProtoView: ProtoView; nestedProtoView: ProtoView;
events:StringMap; events:StringMap;
contentTagSelector:string;
parent:ElementBinder;
index:int;
distanceToParent:int;
constructor( constructor(
index:int, parent:ElementBinder, distanceToParent: int,
protoElementInjector: ProtoElementInjector, componentDirective:DirectiveMetadata, protoElementInjector: ProtoElementInjector, componentDirective:DirectiveMetadata,
viewportDirective:DirectiveMetadata) { viewportDirective:DirectiveMetadata) {
if (isBlank(index)) {
throw new BaseException('null index not allowed.');
}
this.protoElementInjector = protoElementInjector; this.protoElementInjector = protoElementInjector;
this.componentDirective = componentDirective; this.componentDirective = componentDirective;
this.viewportDirective = viewportDirective; this.viewportDirective = viewportDirective;
this.parent = parent;
this.index = index;
this.distanceToParent = distanceToParent;
// updated later when events are bound // updated later when events are bound
this.events = null; this.events = null;
// updated later when text nodes are bound // updated later when text nodes are bound
@ -25,5 +38,7 @@ export class ElementBinder {
this.hasElementPropertyBindings = false; this.hasElementPropertyBindings = false;
// updated later, so we are able to resolve cycles // updated later, so we are able to resolve cycles
this.nestedProtoView = null; this.nestedProtoView = null;
// updated later in the compilation pipeline
this.contentTagSelector = null;
} }
} }

View File

@ -5,7 +5,6 @@ import {Injector, Key, Dependency, bind, Binding, NoProviderError, ProviderError
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility'; import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
import {EventEmitter, PropertySetter} from 'angular2/src/core/annotations/di'; import {EventEmitter, PropertySetter} from 'angular2/src/core/annotations/di';
import * as viewModule from 'angular2/src/core/compiler/view'; import * as viewModule from 'angular2/src/core/compiler/view';
import {LightDom, DestinationLightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom';
import {ViewContainer} from 'angular2/src/core/compiler/view_container'; import {ViewContainer} from 'angular2/src/core/compiler/view_container';
import {NgElement} from 'angular2/src/core/dom/element'; import {NgElement} from 'angular2/src/core/dom/element';
import {Directive, onChange, onDestroy} from 'angular2/src/core/annotations/annotations' import {Directive, onChange, onDestroy} from 'angular2/src/core/annotations/annotations'
@ -24,8 +23,6 @@ class StaticKeys {
viewId:number; viewId:number;
ngElementId:number; ngElementId:number;
viewContainerId:number; viewContainerId:number;
destinationLightDomId:number;
lightDomId:number;
bindingPropagationConfigId:number; bindingPropagationConfigId:number;
constructor() { constructor() {
@ -33,8 +30,6 @@ class StaticKeys {
this.viewId = Key.get(viewModule.View).id; this.viewId = Key.get(viewModule.View).id;
this.ngElementId = Key.get(NgElement).id; this.ngElementId = Key.get(NgElement).id;
this.viewContainerId = Key.get(ViewContainer).id; this.viewContainerId = Key.get(ViewContainer).id;
this.destinationLightDomId = Key.get(DestinationLightDom).id;
this.lightDomId = Key.get(LightDom).id;
this.bindingPropagationConfigId = Key.get(BindingPropagationConfig).id; this.bindingPropagationConfigId = Key.get(BindingPropagationConfig).id;
} }
@ -166,14 +161,12 @@ export class PreBuiltObjects {
view:viewModule.View; view:viewModule.View;
element:NgElement; element:NgElement;
viewContainer:ViewContainer; viewContainer:ViewContainer;
lightDom:LightDom;
bindingPropagationConfig:BindingPropagationConfig; bindingPropagationConfig:BindingPropagationConfig;
constructor(view, element:NgElement, viewContainer:ViewContainer, lightDom:LightDom, constructor(view, element:NgElement, viewContainer:ViewContainer,
bindingPropagationConfig:BindingPropagationConfig) { bindingPropagationConfig:BindingPropagationConfig) {
this.view = view; this.view = view;
this.element = element; this.element = element;
this.viewContainer = viewContainer; this.viewContainer = viewContainer;
this.lightDom = lightDom;
this.bindingPropagationConfig = bindingPropagationConfig; this.bindingPropagationConfig = bindingPropagationConfig;
} }
} }
@ -577,13 +570,6 @@ export class ElementInjector extends TreeNode {
if (keyId === staticKeys.ngElementId) return this._preBuiltObjects.element; if (keyId === staticKeys.ngElementId) return this._preBuiltObjects.element;
if (keyId === staticKeys.viewContainerId) return this._preBuiltObjects.viewContainer; if (keyId === staticKeys.viewContainerId) return this._preBuiltObjects.viewContainer;
if (keyId === staticKeys.bindingPropagationConfigId) return this._preBuiltObjects.bindingPropagationConfig; if (keyId === staticKeys.bindingPropagationConfigId) return this._preBuiltObjects.bindingPropagationConfig;
if (keyId === staticKeys.destinationLightDomId) {
var p:ElementInjector = this.directParent();
return isPresent(p) ? p._preBuiltObjects.lightDom : null;
}
if (keyId === staticKeys.lightDomId) {
return this._preBuiltObjects.lightDom;
}
//TODO add other objects as needed //TODO add other objects as needed
return _undefined; return _undefined;

View File

@ -36,10 +36,12 @@ export class CompileElement {
inheritedProtoView:ProtoView; inheritedProtoView:ProtoView;
inheritedProtoElementInjector:ProtoElementInjector; inheritedProtoElementInjector:ProtoElementInjector;
inheritedElementBinder:ElementBinder; inheritedElementBinder:ElementBinder;
distanceToParentInjector:number; distanceToParentInjector:int;
distanceToParentBinder:int;
compileChildren: boolean; compileChildren: boolean;
ignoreBindings: boolean; ignoreBindings: boolean;
elementDescription: string; // e.g. '<div [class]="foo">' : used to provide context in case of error elementDescription: string; // e.g. '<div [class]="foo">' : used to provide context in case of error
contentTagSelector: string;
constructor(element, compilationUnit = '') { constructor(element, compilationUnit = '') {
this.element = element; this.element = element;
@ -65,9 +67,11 @@ export class CompileElement {
// an own elementBinder // an own elementBinder
this.inheritedElementBinder = null; this.inheritedElementBinder = null;
this.distanceToParentInjector = 0; this.distanceToParentInjector = 0;
this.distanceToParentBinder = 0;
this.compileChildren = true; this.compileChildren = true;
// set to true to ignore all the bindings on the element // set to true to ignore all the bindings on the element
this.ignoreBindings = false; this.ignoreBindings = false;
this.contentTagSelector = null;
// description is calculated here as compilation steps may change the element // description is calculated here as compilation steps may change the element
var tplDesc = assertionsEnabled()? getElementDescription(element) : null; var tplDesc = assertionsEnabled()? getElementDescription(element) : null;
if (compilationUnit !== '') { if (compilationUnit !== '') {

View File

@ -1,6 +1,5 @@
import {ChangeDetection, Parser} from 'angular2/change_detection'; import {ChangeDetection, Parser} from 'angular2/change_detection';
import {List, ListWrapper} from 'angular2/src/facade/collection'; import {List, ListWrapper} from 'angular2/src/facade/collection';
import {isPresent} from 'angular2/src/facade/lang';
import {PropertyBindingParser} from './property_binding_parser'; import {PropertyBindingParser} from './property_binding_parser';
import {TextInterpolationParser} from './text_interpolation_parser'; import {TextInterpolationParser} from './text_interpolation_parser';
@ -32,6 +31,7 @@ export function createDefaultSteps(
var steps = [ var steps = [
new ViewSplitter(parser), new ViewSplitter(parser),
cssProcessor.getCompileStep(compiledComponent, shadowDomStrategy, templateUrl), cssProcessor.getCompileStep(compiledComponent, shadowDomStrategy, templateUrl),
shadowDomStrategy.getTemplateCompileStep(compiledComponent),
new PropertyBindingParser(parser), new PropertyBindingParser(parser),
new DirectiveParser(directives), new DirectiveParser(directives),
new TextInterpolationParser(parser), new TextInterpolationParser(parser),
@ -41,10 +41,5 @@ export function createDefaultSteps(
new ElementBinderBuilder(parser), new ElementBinderBuilder(parser),
]; ];
var shadowDomStep = shadowDomStrategy.getTemplateCompileStep(compiledComponent);
if (isPresent(shadowDomStep)) {
ListWrapper.push(steps, shadowDomStep);
}
return steps; return steps;
} }

View File

@ -49,7 +49,8 @@ export class DirectiveParser extends CompileStep {
var classList = current.classList(); var classList = current.classList();
var cssSelector = new CssSelector(); var cssSelector = new CssSelector();
cssSelector.setElement(DOM.nodeName(current.element)); var nodeName = DOM.nodeName(current.element);
cssSelector.setElement(nodeName);
for (var i=0; i < classList.length; i++) { for (var i=0; i < classList.length; i++) {
cssSelector.addClassName(classList[i]); cssSelector.addClassName(classList[i]);
} }

View File

@ -135,6 +135,11 @@ export class ElementBinderBuilder extends CompileStep {
process(parent:CompileElement, current:CompileElement, control:CompileControl) { process(parent:CompileElement, current:CompileElement, control:CompileControl) {
var elementBinder = null; var elementBinder = null;
var parentElementBinder = null;
var distanceToParentBinder = this._getDistanceToParentBinder(parent, current);
if (isPresent(parent)) {
parentElementBinder = parent.inheritedElementBinder;
}
if (current.hasBindings) { if (current.hasBindings) {
var protoView = current.inheritedProtoView; var protoView = current.inheritedProtoView;
var protoInjectorWasBuilt = isBlank(parent) ? true : var protoInjectorWasBuilt = isBlank(parent) ? true :
@ -143,8 +148,9 @@ export class ElementBinderBuilder extends CompileStep {
var currentProtoElementInjector = protoInjectorWasBuilt ? var currentProtoElementInjector = protoInjectorWasBuilt ?
current.inheritedProtoElementInjector : null; current.inheritedProtoElementInjector : null;
elementBinder = protoView.bindElement(currentProtoElementInjector, elementBinder = protoView.bindElement(parentElementBinder, distanceToParentBinder,
current.componentDirective, current.viewportDirective); currentProtoElementInjector, current.componentDirective, current.viewportDirective);
current.distanceToParentBinder = 0;
if (isPresent(current.textNodeBindings)) { if (isPresent(current.textNodeBindings)) {
this._bindTextNodes(protoView, current); this._bindTextNodes(protoView, current);
@ -155,15 +161,23 @@ export class ElementBinderBuilder extends CompileStep {
if (isPresent(current.eventBindings)) { if (isPresent(current.eventBindings)) {
this._bindEvents(protoView, current); this._bindEvents(protoView, current);
} }
if (isPresent(current.contentTagSelector)) {
elementBinder.contentTagSelector = current.contentTagSelector;
}
var directives = current.getAllDirectives(); var directives = current.getAllDirectives();
this._bindDirectiveProperties(directives, current); this._bindDirectiveProperties(directives, current);
this._bindDirectiveEvents(directives, current); this._bindDirectiveEvents(directives, current);
} else if (isPresent(parent)) { } else if (isPresent(parent)) {
elementBinder = parent.inheritedElementBinder; elementBinder = parentElementBinder;
current.distanceToParentBinder = distanceToParentBinder;
} }
current.inheritedElementBinder = elementBinder; current.inheritedElementBinder = elementBinder;
} }
_getDistanceToParentBinder(parent, current) {
return isPresent(parent) ? parent.distanceToParentBinder + 1 : 0;
}
_bindTextNodes(protoView, compileElement) { _bindTextNodes(protoView, compileElement) {
MapWrapper.forEach(compileElement.textNodeBindings, (expression, indexInParent) => { MapWrapper.forEach(compileElement.textNodeBindings, (expression, indexInParent) => {
protoView.bindTextNode(indexInParent, expression); protoView.bindTextNode(indexInParent, expression);

View File

@ -37,7 +37,8 @@ export class ElementBindingMarker extends CompileStep {
(isPresent(current.eventBindings) && MapWrapper.size(current.eventBindings)>0) || (isPresent(current.eventBindings) && MapWrapper.size(current.eventBindings)>0) ||
(isPresent(current.decoratorDirectives) && current.decoratorDirectives.length > 0) || (isPresent(current.decoratorDirectives) && current.decoratorDirectives.length > 0) ||
isPresent(current.viewportDirective) || isPresent(current.viewportDirective) ||
isPresent(current.componentDirective); isPresent(current.componentDirective) ||
isPresent(current.contentTagSelector);
if (hasBindings) { if (hasBindings) {
var element = current.element; var element = current.element;

View File

@ -1,10 +1,7 @@
import {Decorator} from '../../annotations/annotations';
import * as ldModule from './light_dom'; import * as ldModule from './light_dom';
import {Inject} from 'angular2/di';
import {DOM} from 'angular2/src/dom/dom_adapter'; import {DOM} from 'angular2/src/dom/dom_adapter';
import {isPresent} from 'angular2/src/facade/lang'; import {isPresent} from 'angular2/src/facade/lang';
import {List, ListWrapper} from 'angular2/src/facade/collection'; import {List, ListWrapper} from 'angular2/src/facade/collection';
import {NgElement} from 'angular2/src/core/dom/element';
class ContentStrategy { class ContentStrategy {
nodes:List; nodes:List;
@ -17,23 +14,16 @@ class ContentStrategy {
* and thus does not affect redistribution. * and thus does not affect redistribution.
*/ */
class RenderedContent extends ContentStrategy { class RenderedContent extends ContentStrategy {
static _lazyScriptTemplate;
beginScript; beginScript;
endScript; endScript;
constructor(contentEl) { constructor(contentEl) {
super(); super();
this._replaceContentElementWithScriptTags(contentEl); this.beginScript = contentEl;
this.endScript = DOM.nextSibling(this.beginScript);
this.nodes = []; this.nodes = [];
} }
_scriptTemplate() {
if (!isPresent(RenderedContent._lazyScriptTemplate)) {
RenderedContent._lazyScriptTemplate = DOM.createScriptTag('type', 'ng/content');
}
return RenderedContent._lazyScriptTemplate;
}
// Inserts the nodes in between the start and end scripts. // Inserts the nodes in between the start and end scripts.
// Previous content is removed. // Previous content is removed.
insert(nodes:List) { insert(nodes:List) {
@ -42,16 +32,6 @@ class RenderedContent extends ContentStrategy {
this._removeNodesUntil(ListWrapper.isEmpty(nodes) ? this.endScript : nodes[0]); this._removeNodesUntil(ListWrapper.isEmpty(nodes) ? this.endScript : nodes[0]);
} }
// Replaces the content tag with a pair of script tags
_replaceContentElementWithScriptTags(contentEl) {
this.beginScript = DOM.clone(this._scriptTemplate());
this.endScript = DOM.clone(this._scriptTemplate());
DOM.insertBefore(contentEl, this.beginScript);
DOM.insertBefore(contentEl, this.endScript);
DOM.removeChild(DOM.parentElement(contentEl), contentEl);
}
_removeNodesUntil(node) { _removeNodesUntil(node) {
var p = DOM.parentElement(this.beginScript); var p = DOM.parentElement(this.beginScript);
for (var next = DOM.nextSibling(this.beginScript); for (var next = DOM.nextSibling(this.beginScript);
@ -83,18 +63,17 @@ class IntermediateContent extends ContentStrategy {
} }
@Decorator({
selector: 'content'
})
export class Content { export class Content {
select:string; select:string;
_strategy:ContentStrategy; _strategy:ContentStrategy;
contentStartElement;
constructor(@Inject(ldModule.DestinationLightDom) destinationLightDom, contentEl:NgElement) { constructor(destinationLightDom:ldModule.LightDom, contentStartEl, selector:string) {
this.select = contentEl.getAttribute('select'); this.select = selector;
this.contentStartElement = contentStartEl;
this._strategy = isPresent(destinationLightDom) ? this._strategy = isPresent(destinationLightDom) ?
new IntermediateContent(destinationLightDom) : new IntermediateContent(destinationLightDom) :
new RenderedContent(contentEl.domElement); new RenderedContent(contentStartEl);
} }
nodes():List { nodes():List {

View File

@ -3,8 +3,6 @@ import {List, ListWrapper} from 'angular2/src/facade/collection';
import {isBlank, isPresent} from 'angular2/src/facade/lang'; import {isBlank, isPresent} from 'angular2/src/facade/lang';
import * as viewModule from '../view'; import * as viewModule from '../view';
import {ElementInjector} from '../element_injector';
import {ViewContainer} from '../view_container';
import {Content} from './content_tag'; import {Content} from './content_tag';
export class DestinationLightDom {} export class DestinationLightDom {}
@ -12,11 +10,13 @@ export class DestinationLightDom {}
class _Root { class _Root {
node; node;
injector:ElementInjector; viewContainer;
content;
constructor(node, injector) { constructor(node, viewContainer, content) {
this.node = node; this.node = node;
this.injector = injector; this.viewContainer = viewContainer;
this.content = content;
} }
} }
@ -52,16 +52,15 @@ export class LightDom {
// Collects the Content directives from the view and all its child views // Collects the Content directives from the view and all its child views
_collectAllContentTags(view: viewModule.View, acc:List<Content>):List<Content> { _collectAllContentTags(view: viewModule.View, acc:List<Content>):List<Content> {
var eis = view.elementInjectors; var contentTags = view.contentTags;
for (var i = 0; i < eis.length; ++i) { var vcs = view.viewContainers;
var ei = eis[i]; for (var i=0; i<vcs.length; i++) {
if (isBlank(ei)) continue; var vc = vcs[i];
var contentTag = contentTags[i];
if (ei.hasDirective(Content)) { if (isPresent(contentTag)) {
ListWrapper.push(acc, ei.get(Content)); ListWrapper.push(acc, contentTag);
}
} else if (ei.hasPreBuiltObject(ViewContainer)) { if (isPresent(vc)) {
var vc = ei.get(ViewContainer);
ListWrapper.forEach(vc.contentTagContainers(), (view) => { ListWrapper.forEach(vc.contentTagContainers(), (view) => {
this._collectAllContentTags(view, acc); this._collectAllContentTags(view, acc);
}); });
@ -81,16 +80,11 @@ export class LightDom {
for (var i = 0; i < roots.length; ++i) { for (var i = 0; i < roots.length; ++i) {
var root = roots[i]; var root = roots[i];
var ei = root.injector;
if (isPresent(ei) && ei.hasPreBuiltObject(ViewContainer)) {
var vc = root.injector.get(ViewContainer);
res = ListWrapper.concat(res, vc.nodes());
} else if (isPresent(ei) && ei.hasDirective(Content)) {
var content = root.injector.get(Content);
res = ListWrapper.concat(res, content.nodes());
if (isPresent(root.viewContainer)) {
res = ListWrapper.concat(res, root.viewContainer.nodes());
} else if (isPresent(root.content)) {
res = ListWrapper.concat(res, root.content.nodes());
} else { } else {
ListWrapper.push(res, root.node); ListWrapper.push(res, root.node);
} }
@ -103,10 +97,24 @@ export class LightDom {
_roots() { _roots() {
if (isPresent(this.roots)) return this.roots; if (isPresent(this.roots)) return this.roots;
var viewInj = this.lightDomView.elementInjectors; var viewContainers = this.lightDomView.viewContainers;
this.roots = ListWrapper.map(this.nodes, (n) => var contentTags = this.lightDomView.contentTags;
new _Root(n, ListWrapper.find(viewInj,
(inj) => isPresent(inj) ? inj.forElement(n) : false))); this.roots = ListWrapper.map(this.nodes, (n) => {
var foundVc = null;
var foundContentTag = null;
for (var i=0; i<viewContainers.length; i++) {
var vc = viewContainers[i];
var contentTag = contentTags[i];
if (isPresent(vc) && vc.templateElement === n) {
foundVc = vc;
}
if (isPresent(contentTag) && contentTag.contentStartElement === n) {
foundContentTag = contentTag;
}
}
return new _Root(n, foundVc, foundContentTag);
});
return this.roots; return this.roots;
} }
@ -119,10 +127,10 @@ function redistributeNodes(contents:List<Content>, nodes:List) {
var select = content.select; var select = content.select;
var matchSelector = (n) => DOM.elementMatches(n, select); var matchSelector = (n) => DOM.elementMatches(n, select);
if (isBlank(select)) { // Empty selector is identical to <content/>
if (select.length === 0) {
content.insert(nodes); content.insert(nodes);
ListWrapper.clear(nodes); ListWrapper.clear(nodes);
} else { } else {
var matchingNodes = ListWrapper.filter(nodes, matchSelector); var matchingNodes = ListWrapper.filter(nodes, matchSelector);
content.insert(matchingNodes); content.insert(matchingNodes);

View File

@ -1,4 +1,4 @@
import {Type, isBlank, isPresent, int} from 'angular2/src/facade/lang'; import {Type, isBlank, isPresent, int, StringWrapper, assertionsEnabled} from 'angular2/src/facade/lang';
import {List, ListWrapper, MapWrapper, Map} from 'angular2/src/facade/collection'; import {List, ListWrapper, MapWrapper, Map} from 'angular2/src/facade/collection';
import {PromiseWrapper} from 'angular2/src/facade/async'; import {PromiseWrapper} from 'angular2/src/facade/async';
@ -6,7 +6,6 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
import * as viewModule from './view'; import * as viewModule from './view';
import {Content} from './shadow_dom_emulation/content_tag';
import {LightDom} from './shadow_dom_emulation/light_dom'; import {LightDom} from './shadow_dom_emulation/light_dom';
import {ShadowCss} from './shadow_dom_emulation/shadow_css'; import {ShadowCss} from './shadow_dom_emulation/shadow_css';
@ -19,20 +18,30 @@ import * as NS from './pipeline/compile_step';
import {CompileElement} from './pipeline/compile_element'; import {CompileElement} from './pipeline/compile_element';
import {CompileControl} from './pipeline/compile_control'; import {CompileControl} from './pipeline/compile_control';
var _EMPTY_STEP;
// Note: fill _EMPTY_STEP to prevent
// problems from cyclic dependencies
function _emptyStep() {
if (isBlank(_EMPTY_STEP)) {
_EMPTY_STEP = new _EmptyCompileStep();
}
return _EMPTY_STEP;
}
export class ShadowDomStrategy { export class ShadowDomStrategy {
attachTemplate(el, view:viewModule.View) {} attachTemplate(el, view:viewModule.View) {}
constructLightDom(lightDomView:viewModule.View, shadowDomView:viewModule.View, el): LightDom { return null; } constructLightDom(lightDomView:viewModule.View, shadowDomView:viewModule.View, el): LightDom { return null; }
polyfillDirectives():List<Type> { return []; }
/** /**
* An optional step that can modify the template style elements. * An optional step that can modify the template style elements.
* *
* @param {DirectiveMetadata} cmpMetadata * @param {DirectiveMetadata} cmpMetadata
* @param {string} templateUrl the template base URL * @param {string} templateUrl the template base URL
* @returns {CompileStep} a compile step to append to the compiler pipeline, null if not required. * @returns {CompileStep} a compile step to append to the compiler pipeline
*/ */
getStyleCompileStep(cmpMetadata: DirectiveMetadata, templateUrl: string): NS.CompileStep { getStyleCompileStep(cmpMetadata: DirectiveMetadata, templateUrl: string): NS.CompileStep {
return null; return _emptyStep();
} }
/** /**
@ -41,9 +50,9 @@ export class ShadowDomStrategy {
* This step could be used to modify the template in order to scope the styles. * This step could be used to modify the template in order to scope the styles.
* *
* @param {DirectiveMetadata} cmpMetadata * @param {DirectiveMetadata} cmpMetadata
* @returns {CompileStep} a compile step to append to the compiler pipeline, null if not required. * @returns {CompileStep} a compile step to append to the compiler pipeline
*/ */
getTemplateCompileStep(cmpMetadata: DirectiveMetadata): NS.CompileStep { return null; } getTemplateCompileStep(cmpMetadata: DirectiveMetadata): NS.CompileStep { return _emptyStep(); }
/** /**
* The application element does not go through the compiler pipeline. * The application element does not go through the compiler pipeline.
@ -87,14 +96,14 @@ export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
return new LightDom(lightDomView, shadowDomView, el); return new LightDom(lightDomView, shadowDomView, el);
} }
polyfillDirectives():List<Type> {
return [Content];
}
getStyleCompileStep(cmpMetadata: DirectiveMetadata, templateUrl: string): NS.CompileStep { getStyleCompileStep(cmpMetadata: DirectiveMetadata, templateUrl: string): NS.CompileStep {
return new _EmulatedUnscopedCssStep(cmpMetadata, templateUrl, this._styleUrlResolver, return new _EmulatedUnscopedCssStep(cmpMetadata, templateUrl, this._styleUrlResolver,
this._styleHost); this._styleHost);
} }
getTemplateCompileStep(cmpMetadata: DirectiveMetadata): NS.CompileStep {
return new _BaseEmulatedShadowDomStep();
}
} }
/** /**
@ -156,7 +165,39 @@ export class NativeShadowDomStrategy extends ShadowDomStrategy {
} }
} }
class _ShimShadowDomStep extends NS.CompileStep { class _BaseEmulatedShadowDomStep extends NS.CompileStep {
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
if (current.ignoreBindings) {
return;
}
var nodeName = DOM.nodeName(current.element);
if (StringWrapper.equals(nodeName.toUpperCase(), 'CONTENT')) {
var attrs = current.attrs();
var selector = MapWrapper.get(attrs, 'select');
current.contentTagSelector = isPresent(selector) ? selector : '';
var contentStart = DOM.createScriptTag('type', 'ng/contentStart');
if (assertionsEnabled()) {
DOM.setAttribute(contentStart, 'select', current.contentTagSelector);
}
var contentEnd = DOM.createScriptTag('type', 'ng/contentEnd');
DOM.insertBefore(current.element, contentStart);
DOM.insertBefore(current.element, contentEnd);
DOM.remove(current.element);
current.element = contentStart;
}
}
}
class _EmptyCompileStep extends NS.CompileStep {
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
}
}
class _ShimShadowDomStep extends _BaseEmulatedShadowDomStep {
_contentAttribute: string; _contentAttribute: string;
constructor(cmpMetadata: DirectiveMetadata) { constructor(cmpMetadata: DirectiveMetadata) {
@ -167,6 +208,7 @@ class _ShimShadowDomStep extends NS.CompileStep {
process(parent:CompileElement, current:CompileElement, control:CompileControl) { process(parent:CompileElement, current:CompileElement, control:CompileControl) {
super.process(parent, current, control);
if (current.ignoreBindings) { if (current.ignoreBindings) {
return; return;
} }

View File

@ -13,7 +13,8 @@ import {IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'angular2/src/f
import {Injector} from 'angular2/di'; import {Injector} from 'angular2/di';
import {NgElement} from 'angular2/src/core/dom/element'; import {NgElement} from 'angular2/src/core/dom/element';
import {ViewContainer} from './view_container'; import {ViewContainer} from './view_container';
import {LightDom, DestinationLightDom} from './shadow_dom_emulation/light_dom'; import {LightDom} from './shadow_dom_emulation/light_dom';
import {Content} from './shadow_dom_emulation/content_tag';
import {ShadowDomStrategy} from './shadow_dom_strategy'; import {ShadowDomStrategy} from './shadow_dom_strategy';
import {ViewPool} from './view_pool'; import {ViewPool} from './view_pool';
import {EventManager} from 'angular2/src/core/events/event_manager'; import {EventManager} from 'angular2/src/core/events/event_manager';
@ -41,7 +42,9 @@ export class View {
nodes:List; nodes:List;
componentChildViews: List<View>; componentChildViews: List<View>;
viewContainers: List<ViewContainer>; viewContainers: List<ViewContainer>;
contentTags: List<Content>;
preBuiltObjects: List<PreBuiltObjects>; preBuiltObjects: List<PreBuiltObjects>;
lightDoms: List<LightDom>;
proto: ProtoView; proto: ProtoView;
context: any; context: any;
contextWithLocals:ContextWithVariableBindings; contextWithLocals:ContextWithVariableBindings;
@ -56,7 +59,9 @@ export class View {
this.bindElements = null; this.bindElements = null;
this.componentChildViews = null; this.componentChildViews = null;
this.viewContainers = null; this.viewContainers = null;
this.contentTags = null;
this.preBuiltObjects = null; this.preBuiltObjects = null;
this.lightDoms = null;
this.context = null; this.context = null;
this.contextWithLocals = (MapWrapper.size(protoContextLocals) > 0) this.contextWithLocals = (MapWrapper.size(protoContextLocals) > 0)
? new ContextWithVariableBindings(null, MapWrapper.clone(protoContextLocals)) ? new ContextWithVariableBindings(null, MapWrapper.clone(protoContextLocals))
@ -64,15 +69,17 @@ export class View {
} }
init(changeDetector:ChangeDetector, elementInjectors:List, rootElementInjectors:List, textNodes: List, bindElements:List, init(changeDetector:ChangeDetector, elementInjectors:List, rootElementInjectors:List, textNodes: List, bindElements:List,
viewContainers:List, preBuiltObjects:List, componentChildViews:List) { viewContainers:List, contentTags:List, preBuiltObjects:List, componentChildViews:List, lightDoms:List<LightDom>) {
this.changeDetector = changeDetector; this.changeDetector = changeDetector;
this.elementInjectors = elementInjectors; this.elementInjectors = elementInjectors;
this.rootElementInjectors = rootElementInjectors; this.rootElementInjectors = rootElementInjectors;
this.textNodes = textNodes; this.textNodes = textNodes;
this.bindElements = bindElements; this.bindElements = bindElements;
this.viewContainers = viewContainers; this.viewContainers = viewContainers;
this.contentTags = contentTags;
this.preBuiltObjects = preBuiltObjects; this.preBuiltObjects = preBuiltObjects;
this.componentChildViews = componentChildViews; this.componentChildViews = componentChildViews;
this.lightDoms = lightDoms;
} }
setLocal(contextName: string, value) { setLocal(contextName: string, value) {
@ -125,14 +132,17 @@ export class View {
* A call to hydrate/dehydrate does not attach/detach the view from the view * A call to hydrate/dehydrate does not attach/detach the view from the view
* tree. * tree.
*/ */
hydrate(appInjector: Injector, hostElementInjector: ElementInjector, hydrate(appInjector: Injector, hostElementInjector: ElementInjector, hostLightDom: LightDom,
context: Object) { context: Object) {
if (this.hydrated()) throw new BaseException('The view is already hydrated.'); if (this.hydrated()) throw new BaseException('The view is already hydrated.');
this._hydrateContext(context); this._hydrateContext(context);
// viewContainers // viewContainers
for (var i = 0; i < this.viewContainers.length; i++) { for (var i = 0; i < this.viewContainers.length; i++) {
this.viewContainers[i].hydrate(appInjector, hostElementInjector); var vc = this.viewContainers[i];
if (isPresent(vc)) {
vc.hydrate(appInjector, hostElementInjector, hostLightDom);
}
} }
var binders = this.proto.elementBinders; var binders = this.proto.elementBinders;
@ -171,21 +181,17 @@ export class View {
if (isPresent(componentDirective)) { if (isPresent(componentDirective)) {
this.componentChildViews[componentChildViewIndex++].hydrate(shadowDomAppInjector, this.componentChildViews[componentChildViewIndex++].hydrate(shadowDomAppInjector,
elementInjector, elementInjector.getComponent()); elementInjector, this.lightDoms[i], elementInjector.getComponent());
} }
} }
// this should be moved into DOM write queue for (var i = 0; i < this.lightDoms.length; ++i) {
for (var i = 0; i < binders.length; ++i) { var lightDom = this.lightDoms[i];
var componentDirective = binders[i].componentDirective;
if (isPresent(componentDirective)) {
var lightDom = this.preBuiltObjects[i].lightDom;
if (isPresent(lightDom)) { if (isPresent(lightDom)) {
lightDom.redistribute(); lightDom.redistribute();
} }
} }
} }
}
dehydrate() { dehydrate() {
// Note: preserve the opposite order of the hydration process. // Note: preserve the opposite order of the hydration process.
@ -205,7 +211,10 @@ export class View {
// viewContainers // viewContainers
if (isPresent(this.viewContainers)) { if (isPresent(this.viewContainers)) {
for (var i = 0; i < this.viewContainers.length; i++) { for (var i = 0; i < this.viewContainers.length; i++) {
this.viewContainers[i].dehydrate(); var vc = this.viewContainers[i];
if (isPresent(vc)) {
vc.dehydrate();
}
} }
} }
@ -370,8 +379,10 @@ export class ProtoView {
var textNodes = []; var textNodes = [];
var elementsWithPropertyBindings = []; var elementsWithPropertyBindings = [];
var preBuiltObjects = ListWrapper.createFixedSize(binders.length); var preBuiltObjects = ListWrapper.createFixedSize(binders.length);
var viewContainers = []; var viewContainers = ListWrapper.createFixedSize(binders.length);
var contentTags = ListWrapper.createFixedSize(binders.length);
var componentChildViews = []; var componentChildViews = [];
var lightDoms = ListWrapper.createFixedSize(binders.length);
for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) { for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) {
var binder = binders[binderIdx]; var binder = binders[binderIdx];
@ -427,20 +438,32 @@ export class ProtoView {
ListWrapper.push(componentChildViews, childView); ListWrapper.push(componentChildViews, childView);
} }
lightDoms[binderIdx] = lightDom;
var destLightDom = null;
if (isPresent(binder.parent) && binder.distanceToParent === 1) {
destLightDom = lightDoms[binder.parent.index];
}
// viewContainers // viewContainers
var viewContainer = null; var viewContainer = null;
if (isPresent(binder.viewportDirective)) { if (isPresent(binder.viewportDirective)) {
var destLightDom = this._directParentElementLightDom(protoElementInjector, preBuiltObjects);
viewContainer = new ViewContainer(view, element, binder.nestedProtoView, elementInjector, viewContainer = new ViewContainer(view, element, binder.nestedProtoView, elementInjector,
eventManager, destLightDom); eventManager, destLightDom);
ListWrapper.push(viewContainers, viewContainer);
} }
viewContainers[binderIdx] = viewContainer;
// contentTags
var contentTag = null;
if (isPresent(binder.contentTagSelector)) {
contentTag = new Content(destLightDom, element, binder.contentTagSelector);
}
contentTags[binderIdx] = contentTag;
// preBuiltObjects // preBuiltObjects
if (isPresent(elementInjector)) { if (isPresent(elementInjector)) {
preBuiltObjects[binderIdx] = new PreBuiltObjects(view, new NgElement(element), viewContainer, preBuiltObjects[binderIdx] = new PreBuiltObjects(view, new NgElement(element), viewContainer,
lightDom, bindingPropagationConfig); bindingPropagationConfig);
} }
// events // events
@ -460,7 +483,7 @@ export class ProtoView {
this.eventHandlers = eventHandlers; this.eventHandlers = eventHandlers;
view.init(changeDetector, elementInjectors, rootElementInjectors, textNodes, elementsWithPropertyBindings, view.init(changeDetector, elementInjectors, rootElementInjectors, textNodes, elementsWithPropertyBindings,
viewContainers, preBuiltObjects, componentChildViews); viewContainers, contentTags, preBuiltObjects, componentChildViews, lightDoms);
return view; return view;
} }
@ -497,19 +520,15 @@ export class ProtoView {
} }
} }
_directParentElementLightDom(protoElementInjector:ProtoElementInjector, preBuiltObjects:List):LightDom {
var p = protoElementInjector.directParent();
return isPresent(p) ? preBuiltObjects[p.index].lightDom : null;
}
bindVariable(contextName:string, templateName:string) { bindVariable(contextName:string, templateName:string) {
MapWrapper.set(this.variableBindings, contextName, templateName); MapWrapper.set(this.variableBindings, contextName, templateName);
MapWrapper.set(this.protoContextLocals, templateName, null); MapWrapper.set(this.protoContextLocals, templateName, null);
} }
bindElement(protoElementInjector:ProtoElementInjector, bindElement(parent:ElementBinder, distanceToParent:int, protoElementInjector:ProtoElementInjector,
componentDirective:DirectiveMetadata = null, viewportDirective:DirectiveMetadata = null):ElementBinder { componentDirective:DirectiveMetadata = null, viewportDirective:DirectiveMetadata = null):ElementBinder {
var elBinder = new ElementBinder(protoElementInjector, componentDirective, viewportDirective); var elBinder = new ElementBinder(this.elementBinders.length, parent, distanceToParent,
protoElementInjector, componentDirective, viewportDirective);
ListWrapper.push(this.elementBinders, elBinder); ListWrapper.push(this.elementBinders, elBinder);
return elBinder; return elBinder;
} }
@ -601,7 +620,7 @@ export class ProtoView {
var cmpType = rootComponentAnnotatedType.type; var cmpType = rootComponentAnnotatedType.type;
var rootProtoView = new ProtoView(insertionElement, protoChangeDetector, shadowDomStrategy); var rootProtoView = new ProtoView(insertionElement, protoChangeDetector, shadowDomStrategy);
rootProtoView.instantiateInPlace = true; rootProtoView.instantiateInPlace = true;
var binder = rootProtoView.bindElement( var binder = rootProtoView.bindElement(null, 0,
new ProtoElementInjector(null, 0, [cmpType], true)); new ProtoElementInjector(null, 0, [cmpType], true));
binder.componentDirective = rootComponentAnnotatedType; binder.componentDirective = rootComponentAnnotatedType;
binder.nestedProtoView = protoView; binder.nestedProtoView = protoView;

View File

@ -40,10 +40,10 @@ export class ViewContainer {
this._eventManager = eventManager; this._eventManager = eventManager;
} }
hydrate(appInjector: Injector, hostElementInjector: eiModule.ElementInjector) { hydrate(appInjector: Injector, hostElementInjector: eiModule.ElementInjector, hostLightDom: ldModule.LightDom) {
this.appInjector = appInjector; this.appInjector = appInjector;
this.hostElementInjector = hostElementInjector; this.hostElementInjector = hostElementInjector;
this.hostLightDom = isPresent(hostElementInjector) ? hostElementInjector.get(ldModule.LightDom) : null; this.hostLightDom = hostLightDom;
} }
dehydrate() { dehydrate() {
@ -85,7 +85,7 @@ export class ViewContainer {
var newView = this.defaultProtoView.instantiate(this.hostElementInjector, this._eventManager); var newView = this.defaultProtoView.instantiate(this.hostElementInjector, this._eventManager);
// insertion must come before hydration so that element injector trees are attached. // insertion must come before hydration so that element injector trees are attached.
this.insert(newView, atIndex); this.insert(newView, atIndex);
newView.hydrate(this.appInjector, this.hostElementInjector, this.parentView.context); newView.hydrate(this.appInjector, this.hostElementInjector, this.hostLightDom, this.parentView.context);
// new content tags might have appeared, we need to redistrubute. // new content tags might have appeared, we need to redistrubute.
if (isPresent(this.hostLightDom)) { if (isPresent(this.hostLightDom)) {

View File

@ -208,6 +208,10 @@ export class RegExpWrapper {
return input.match(regExp.single); return input.match(regExp.single);
} }
static matcher(regExp, input) { static matcher(regExp, input) {
// Reset regex state for the case
// someone did not loop over all matches
// last time.
regExp.multiple.lastIndex = 0;
return { return {
re: regExp.multiple, re: regExp.multiple,
input: input input: input

View File

@ -115,7 +115,7 @@ export function runCompilerCommonTests() {
if (DOM.hasClass(current.element, 'nested')) { if (DOM.hasClass(current.element, 'nested')) {
current.componentDirective = reader.read(NestedComponent); current.componentDirective = reader.read(NestedComponent);
current.inheritedProtoView = parent.inheritedProtoView; current.inheritedProtoView = parent.inheritedProtoView;
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null); current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
} else { } else {
current.inheritedProtoView = new ProtoView(current.element, null, null); current.inheritedProtoView = new ProtoView(current.element, null, null);
} }
@ -148,7 +148,7 @@ export function runCompilerCommonTests() {
var compiler = createCompiler( (parent, current, control) => { var compiler = createCompiler( (parent, current, control) => {
current.inheritedProtoView = new ProtoView(current.element, null, null); current.inheritedProtoView = new ProtoView(current.element, null, null);
if (DOM.hasClass(current.element, 'nested')) { if (DOM.hasClass(current.element, 'nested')) {
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null); current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
current.componentDirective = reader.read(NestedComponent); current.componentDirective = reader.read(NestedComponent);
ListWrapper.push(nestedElBinders, current.inheritedElementBinder); ListWrapper.push(nestedElBinders, current.inheritedElementBinder);
} }
@ -164,7 +164,7 @@ export function runCompilerCommonTests() {
it('should allow recursive components', inject([AsyncTestCompleter], (async) => { it('should allow recursive components', inject([AsyncTestCompleter], (async) => {
var compiler = createCompiler( (parent, current, control) => { var compiler = createCompiler( (parent, current, control) => {
current.inheritedProtoView = new ProtoView(current.element, null, null); current.inheritedProtoView = new ProtoView(current.element, null, null);
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null); current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
current.componentDirective = reader.read(RecursiveComponent); current.componentDirective = reader.read(RecursiveComponent);
}); });
compiler.compile(RecursiveComponent).then( (protoView) => { compiler.compile(RecursiveComponent).then( (protoView) => {
@ -193,7 +193,7 @@ export function runCompilerCommonTests() {
if (DOM.hasClass(current.element, 'parent')) { if (DOM.hasClass(current.element, 'parent')) {
current.componentDirective = reader.read(NestedComponent); current.componentDirective = reader.read(NestedComponent);
current.inheritedProtoView = parent.inheritedProtoView; current.inheritedProtoView = parent.inheritedProtoView;
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null); current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null);
} else { } else {
current.inheritedProtoView = new ProtoView(current.element, null, null); current.inheritedProtoView = new ProtoView(current.element, null, null);
} }

View File

@ -113,7 +113,7 @@ class DirectiveWithDestroy {
} }
export function main() { export function main() {
var defaultPreBuiltObjects = new PreBuiltObjects(null, null, null, null, null); var defaultPreBuiltObjects = new PreBuiltObjects(null, null, null, null);
function humanize(tree, names:List) { function humanize(tree, names:List) {
var lookupName = (item) => var lookupName = (item) =>
@ -283,7 +283,7 @@ export function main() {
it("should instantiate directives that depend on pre built objects", function () { it("should instantiate directives that depend on pre built objects", function () {
var view = new DummyView(); var view = new DummyView();
var inj = injector([NeedsView], null, null, new PreBuiltObjects(view, null, null, null, null)); var inj = injector([NeedsView], null, null, new PreBuiltObjects(view, null, null, null));
expect(inj.get(NeedsView).view).toBe(view); expect(inj.get(NeedsView).view).toBe(view);
}); });
@ -420,52 +420,31 @@ export function main() {
describe("pre built objects", function () { describe("pre built objects", function () {
it("should return view", function () { it("should return view", function () {
var view = new DummyView(); var view = new DummyView();
var inj = injector([], null, null, new PreBuiltObjects(view, null, null, null, null)); var inj = injector([], null, null, new PreBuiltObjects(view, null, null, null));
expect(inj.get(View)).toEqual(view); expect(inj.get(View)).toEqual(view);
}); });
it("should return element", function () { it("should return element", function () {
var element = new NgElement(null); var element = new NgElement(null);
var inj = injector([], null, null, new PreBuiltObjects(null, element, null, null, null)); var inj = injector([], null, null, new PreBuiltObjects(null, element, null, null));
expect(inj.get(NgElement)).toEqual(element); expect(inj.get(NgElement)).toEqual(element);
}); });
it('should return viewContainer', function () { it('should return viewContainer', function () {
var viewContainer = new ViewContainer(null, null, null, null, null); var viewContainer = new ViewContainer(null, null, null, null, null);
var inj = injector([], null, null, new PreBuiltObjects(null, null, viewContainer, null, null)); var inj = injector([], null, null, new PreBuiltObjects(null, null, viewContainer, null));
expect(inj.get(ViewContainer)).toEqual(viewContainer); expect(inj.get(ViewContainer)).toEqual(viewContainer);
}); });
it('should return bindingPropagationConfig', function () { it('should return bindingPropagationConfig', function () {
var config = new BindingPropagationConfig(null); var config = new BindingPropagationConfig(null);
var inj = injector([], null, null, new PreBuiltObjects(null, null, null, null, config)); var inj = injector([], null, null, new PreBuiltObjects(null, null, null, config));
expect(inj.get(BindingPropagationConfig)).toEqual(config); expect(inj.get(BindingPropagationConfig)).toEqual(config);
}); });
describe("light DOM", () => {
var lightDom, parentPreBuiltObjects;
beforeEach(() => {
lightDom = new DummyLightDom();
parentPreBuiltObjects = new PreBuiltObjects(null, null, null, lightDom, null);
});
it("should return light DOM from the current injector", function () {
var inj = injector([], null, null, parentPreBuiltObjects);
expect(inj.get(LightDom)).toEqual(lightDom);
});
it("should return null when parent's injector is a component boundary", function () {
var child = hostShadowInjectors([], [], parentPreBuiltObjects);
expect(child.get(DestinationLightDom)).toBeNull();
});
});
}); });
describe('event emitters', () => { describe('event emitters', () => {
@ -476,7 +455,7 @@ export function main() {
var pv = new ProtoView(null, null, null); var pv = new ProtoView(null, null, null);
pv.eventHandlers = [handlers]; pv.eventHandlers = [handlers];
var view = new View(pv, null, MapWrapper.create()); var view = new View(pv, null, MapWrapper.create());
var preBuildObject = new PreBuiltObjects(view, null, null, null, null); var preBuildObject = new PreBuiltObjects(view, null, null, null);
var inj = injector([NeedsEventEmitter], null, null, preBuildObject); var inj = injector([NeedsEventEmitter], null, null, preBuildObject);
inj.get(NeedsEventEmitter).click(); inj.get(NeedsEventEmitter).click();
expect(called).toEqual(true); expect(called).toEqual(true);
@ -494,7 +473,7 @@ export function main() {
var div = el('<div></div>'); var div = el('<div></div>');
var ngElement = new NgElement(div); var ngElement = new NgElement(div);
var preBuildObject = new PreBuiltObjects(null, ngElement, null, null, null); var preBuildObject = new PreBuiltObjects(null, ngElement, null, null);
var inj = injector([NeedsPropertySetter], null, null, preBuildObject); var inj = injector([NeedsPropertySetter], null, null, preBuildObject);
inj.get(NeedsPropertySetter).setProp('foobar'); inj.get(NeedsPropertySetter).setProp('foobar');

View File

@ -68,7 +68,7 @@ export function main() {
function createView(pv) { function createView(pv) {
ctx = new MyComp(); ctx = new MyComp();
view = pv.instantiate(null, null); view = pv.instantiate(null, null);
view.hydrate(new Injector([]), null, ctx); view.hydrate(new Injector([]), null, null, ctx);
cd = view.changeDetector; cd = view.changeDetector;
} }
@ -479,7 +479,8 @@ export function main() {
createView(pv); createView(pv);
cd.detectChanges(); cd.detectChanges();
var subview = view.viewContainers[0].get(0); // Note: viewContainers is a sparse array!
var subview = view.viewContainers[1].get(0);
var childComponent = subview.contextWithLocals.get('child'); var childComponent = subview.contextWithLocals.get('child');
expect(childComponent.myAncestor).toBeAnInstanceOf(SomeDirective); expect(childComponent.myAncestor).toBeAnInstanceOf(SomeDirective);

View File

@ -83,7 +83,7 @@ export function main() {
function instantiateView(protoView) { function instantiateView(protoView) {
evalContext = new Context(); evalContext = new Context();
view = protoView.instantiate(null, null); view = protoView.instantiate(null, null);
view.hydrate(new Injector([]), null, evalContext); view.hydrate(new Injector([]), null, null, evalContext);
changeDetector = view.changeDetector; changeDetector = view.changeDetector;
} }

View File

@ -21,7 +21,7 @@ export function main() {
if (isPresent(DOM.getAttribute(current.element, 'var-binding'))) { if (isPresent(DOM.getAttribute(current.element, 'var-binding'))) {
current.variableBindings = MapWrapper.createFromStringMap(variableBindings); current.variableBindings = MapWrapper.createFromStringMap(variableBindings);
} }
current.inheritedElementBinder = new ElementBinder(null, null, null); current.inheritedElementBinder = new ElementBinder(0, null, 0, null, null, null);
}), new ProtoViewBuilder(dynamicChangeDetection, new NativeShadowDomStrategy(null))]); }), new ProtoViewBuilder(dynamicChangeDetection, new NativeShadowDomStrategy(null))]);
} }

View File

@ -2,47 +2,46 @@ import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el, proxy}
import {IMPLEMENTS} from 'angular2/src/facade/lang'; import {IMPLEMENTS} from 'angular2/src/facade/lang';
import {DOM} from 'angular2/src/dom/dom_adapter'; import {DOM} from 'angular2/src/dom/dom_adapter';
import {Content} from 'angular2/src/core/compiler/shadow_dom_emulation/content_tag'; import {Content} from 'angular2/src/core/compiler/shadow_dom_emulation/content_tag';
import {NgElement} from 'angular2/src/core/dom/element';
import {LightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom'; import {LightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom';
@proxy @proxy
@IMPLEMENTS(LightDom) @IMPLEMENTS(LightDom)
class DummyLightDom extends SpyObject {noSuchMethod(m){super.noSuchMethod(m)}} class DummyLightDom extends SpyObject {noSuchMethod(m){super.noSuchMethod(m)}}
var _script = `<script type="ng/content"></script>`; var _scriptStart = `<script start=""></script>`;
var _scriptEnd = `<script end=""></script>`;
export function main() { export function main() {
describe('Content', function() { describe('Content', function() {
it("should insert the nodes", () => { var parent;
var parent = el("<div><content></content></div>"); var content;
var content = DOM.firstChild(parent);
var c = new Content(null, new NgElement(content)); beforeEach(() => {
parent = el(`<div>${_scriptStart}${_scriptEnd}`);
content = DOM.firstChild(parent);
});
it("should insert the nodes", () => {
var c = new Content(null, content, '');
c.insert([el("<a></a>"), el("<b></b>")]) c.insert([el("<a></a>"), el("<b></b>")])
expect(DOM.getInnerHTML(parent)).toEqual(`${_script}<a></a><b></b>${_script}`); expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}<a></a><b></b>${_scriptEnd}`);
}); });
it("should remove the nodes from the previous insertion", () => { it("should remove the nodes from the previous insertion", () => {
var parent = el("<div><content></content></div>"); var c = new Content(null, content, '');
var content = DOM.firstChild(parent);
var c = new Content(null, new NgElement(content));
c.insert([el("<a></a>")]); c.insert([el("<a></a>")]);
c.insert([el("<b></b>")]); c.insert([el("<b></b>")]);
expect(DOM.getInnerHTML(parent)).toEqual(`${_script}<b></b>${_script}`); expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}<b></b>${_scriptEnd}`);
}); });
it("should insert empty list", () => { it("should insert empty list", () => {
var parent = el("<div><content></content></div>"); var c = new Content(null, content, '');
var content = DOM.firstChild(parent);
var c = new Content(null, new NgElement(content));
c.insert([el("<a></a>")]); c.insert([el("<a></a>")]);
c.insert([]); c.insert([]);
expect(DOM.getInnerHTML(parent)).toEqual(`${_script}${_script}`); expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}${_scriptEnd}`);
}); });
}); });
} }

View File

@ -1,56 +1,35 @@
import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el, proxy} from 'angular2/test_lib'; import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el, proxy} from 'angular2/test_lib';
import {IMPLEMENTS, isBlank} from 'angular2/src/facade/lang'; import {IMPLEMENTS, isBlank, isPresent} from 'angular2/src/facade/lang';
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection'; import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/dom/dom_adapter'; import {DOM} from 'angular2/src/dom/dom_adapter';
import {Content} from 'angular2/src/core/compiler/shadow_dom_emulation/content_tag'; import {Content} from 'angular2/src/core/compiler/shadow_dom_emulation/content_tag';
import {LightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom'; import {LightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom';
import {View} from 'angular2/src/core/compiler/view'; import {View} from 'angular2/src/core/compiler/view';
import {ViewContainer} from 'angular2/src/core/compiler/view_container'; import {ViewContainer} from 'angular2/src/core/compiler/view_container';
import {ElementInjector} from 'angular2/src/core/compiler/element_injector';
@proxy
@IMPLEMENTS(ElementInjector)
class FakeElementInjector {
content;
viewContainer;
element;
constructor(content = null, viewContainer = null, element = null) {
this.content = content;
this.viewContainer = viewContainer;
this.element = element;
}
hasDirective(type) {
return this.content != null;
}
hasPreBuiltObject(type) {
return this.viewContainer != null;
}
forElement(n) {
return this.element == n;
}
get(t) {
if (t === Content) return this.content;
if (t === ViewContainer) return this.viewContainer;
return null;
}
noSuchMethod(i) {
super.noSuchMethod(i);
}
}
@proxy @proxy
@IMPLEMENTS(View) @IMPLEMENTS(View)
class FakeView { class FakeView {
elementInjectors; contentTags;
viewContainers;
constructor(elementInjectors = null) { constructor(containers = null) {
this.elementInjectors = elementInjectors; this.contentTags = [];
this.viewContainers = [];
if (isPresent(containers)) {
ListWrapper.forEach(containers, (c) => {
if (c instanceof FakeContentTag) {
ListWrapper.push(this.contentTags, c);
} else {
ListWrapper.push(this.contentTags, null);
}
if (c instanceof FakeViewContainer) {
ListWrapper.push(this.viewContainers, c);
} else {
ListWrapper.push(this.viewContainers, null);
}
});
}
} }
noSuchMethod(i) { noSuchMethod(i) {
@ -61,10 +40,12 @@ class FakeView {
@proxy @proxy
@IMPLEMENTS(ViewContainer) @IMPLEMENTS(ViewContainer)
class FakeViewContainer { class FakeViewContainer {
templateElement;
_nodes; _nodes;
_contentTagContainers; _contentTagContainers;
constructor(nodes = null, views = null) { constructor(templateEl, nodes = null, views = null) {
this.templateElement = templateEl;
this._nodes = nodes; this._nodes = nodes;
this._contentTagContainers = views; this._contentTagContainers = views;
} }
@ -88,8 +69,10 @@ class FakeViewContainer {
class FakeContentTag { class FakeContentTag {
select; select;
_nodes; _nodes;
contentStartElement;
constructor(select = null, nodes = null) { constructor(contentEl, select = '', nodes = null) {
this.contentStartElement = contentEl;
this.select = select; this.select = select;
this._nodes = nodes; this._nodes = nodes;
} }
@ -113,69 +96,66 @@ export function main() {
var lightDomView; var lightDomView;
beforeEach(() => { beforeEach(() => {
lightDomView = new FakeView([]); lightDomView = new FakeView();
}); });
describe("contentTags", () => { describe("contentTags", () => {
it("should collect content tags from element injectors", () => { it("should collect content tags from element injectors", () => {
var tag = new FakeContentTag(); var tag = new FakeContentTag(el('<script></script>'));
var shadowDomView = new FakeView([new FakeElementInjector(tag)]); var shadowDomView = new FakeView([tag]);
var lightDom = new LightDom(lightDomView, shadowDomView, el("<div></div>")); var lightDom = new LightDom(lightDomView, shadowDomView,
el("<div></div>"));
expect(lightDom.contentTags()).toEqual([tag]); expect(lightDom.contentTags()).toEqual([tag]);
}); });
it("should collect content tags from ViewContainers", () => { it("should collect content tags from ViewContainers", () => {
var tag = new FakeContentTag(); var tag = new FakeContentTag(el('<script></script>'));
var vp = new FakeViewContainer(null, [ var vc = new FakeViewContainer(null, null, [
new FakeView([new FakeElementInjector(tag, null)]) new FakeView([tag])
]); ]);
var shadowDomView = new FakeView([vc]);
var shadowDomView = new FakeView([new FakeElementInjector(null, vp)]); var lightDom = new LightDom(lightDomView, shadowDomView,
el("<div></div>"));
var lightDom = new LightDom(lightDomView, shadowDomView, el("<div></div>"));
expect(lightDom.contentTags()).toEqual([tag]); expect(lightDom.contentTags()).toEqual([tag]);
}); });
}); });
describe("expanded roots", () => { describe("expandedDomNodes", () => {
it("should contain root nodes", () => { it("should contain root nodes", () => {
var lightDomEl = el("<div><a></a></div>") var lightDomEl = el("<div><a></a></div>")
var lightDom = new LightDom(lightDomView, new FakeView(), lightDomEl); var lightDom = new LightDom(lightDomView, new FakeView(), lightDomEl);
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]); expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
}); });
it("should include ViewContainer nodes", () => { it("should include view container nodes", () => {
var lightDomEl = el("<div><template></template></div>") var lightDomEl = el("<div><template></template></div>");
var lightDomView = new FakeView([
new FakeElementInjector(
null,
new FakeViewContainer([el("<a></a>")]),
DOM.firstChild(lightDomEl))]);
var lightDom = new LightDom( var lightDom = new LightDom(
lightDomView, new FakeView([
new FakeView(), new FakeViewContainer(
DOM.firstChild(lightDomEl), // template element
[el('<a></a>')] // light DOM nodes of view container
)
]),
null,
lightDomEl); lightDomEl);
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]); expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
}); });
it("should include content nodes", () => { it("should include content nodes", () => {
var lightDomEl = el("<div><content></content></div>") var lightDomEl = el("<div><content></content></div>");
var lightDomView = new FakeView([
new FakeElementInjector(
new FakeContentTag(null, [el("<a></a>")]),
null,
DOM.firstChild(lightDomEl))]);
var lightDom = new LightDom( var lightDom = new LightDom(
lightDomView, new FakeView([
new FakeView(), new FakeContentTag(
DOM.firstChild(lightDomEl), // content element
'', // selector
[el('<a></a>')] // light DOM nodes of content tag
)
]),
null,
lightDomEl); lightDomEl);
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]); expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
@ -184,7 +164,7 @@ export function main() {
it("should work when the element injector array contains nulls", () => { it("should work when the element injector array contains nulls", () => {
var lightDomEl = el("<div><a></a></div>") var lightDomEl = el("<div><a></a></div>")
var lightDomView = new FakeView([null]); var lightDomView = new FakeView();
var lightDom = new LightDom( var lightDom = new LightDom(
lightDomView, lightDomView,
@ -197,14 +177,14 @@ export function main() {
describe("redistribute", () => { describe("redistribute", () => {
it("should redistribute nodes between content tags with select property set", () => { it("should redistribute nodes between content tags with select property set", () => {
var contentA = new FakeContentTag("a"); var contentA = new FakeContentTag(null, "a");
var contentB = new FakeContentTag("b"); var contentB = new FakeContentTag(null, "b");
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>") var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>")
var lightDom = new LightDom(lightDomView, new FakeView([ var lightDom = new LightDom(lightDomView, new FakeView([
new FakeElementInjector(contentA, null), contentA,
new FakeElementInjector(contentB, null) contentB
]), lightDomEl); ]), lightDomEl);
lightDom.redistribute(); lightDom.redistribute();
@ -214,14 +194,14 @@ export function main() {
}); });
it("should support wildcard content tags", () => { it("should support wildcard content tags", () => {
var wildcard = new FakeContentTag(null); var wildcard = new FakeContentTag(null, '');
var contentB = new FakeContentTag("b"); var contentB = new FakeContentTag(null, "b");
var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>") var lightDomEl = el("<div><a>1</a><b>2</b><a>3</a></div>")
var lightDom = new LightDom(lightDomView, new FakeView([ var lightDom = new LightDom(lightDomView, new FakeView([
new FakeElementInjector(wildcard, null), wildcard,
new FakeElementInjector(contentB, null) contentB
]), lightDomEl); ]), lightDomEl);
lightDom.redistribute(); lightDom.redistribute();

View File

@ -92,6 +92,18 @@ export function main() {
}); });
} }
it('should support simple components', inject([AsyncTestCompleter], (async) => {
var temp = '<simple>' +
'<div>A</div>' +
'</simple>';
compile(temp, [Simple], (view, lc) => {
expect(view.nodes).toHaveText('SIMPLE(A)');
async.done();
});
}));
it('should support multiple content tags', inject([AsyncTestCompleter], (async) => { it('should support multiple content tags', inject([AsyncTestCompleter], (async) => {
var temp = '<multiple-content-tags>' + var temp = '<multiple-content-tags>' +
'<div>B</div>' + '<div>B</div>' +
@ -367,6 +379,6 @@ class MyComp {
function createView(pv) { function createView(pv) {
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(new Injector([]), null, {}); view.hydrate(new Injector([]), null, null, {});
return view; return view;
} }

View File

@ -56,10 +56,6 @@ export function main() {
expect(shadowRoot).toHaveText('view'); expect(shadowRoot).toHaveText('view');
}); });
it('should should not transform template elements', () => {
expect(strategy.getTemplateCompileStep(null)).toBe(null);
});
it('should rewrite style urls', () => { it('should rewrite style urls', () => {
var step = strategy.getStyleCompileStep(null, 'http://base'); var step = strategy.getStyleCompileStep(null, 'http://base');
var styleElement = DOM.createStyleElement('.one {background-image: url("img.jpg");}'); var styleElement = DOM.createStyleElement('.one {background-image: url("img.jpg");}');

View File

@ -12,7 +12,7 @@ import {DynamicProtoChangeDetector, ChangeDetector, Lexer, Parser} from 'angular
function createView(nodes) { function createView(nodes) {
var view = new View(null, nodes, MapWrapper.create()); var view = new View(null, nodes, MapWrapper.create());
var cd = new DynamicProtoChangeDetector(null).instantiate(view, []); var cd = new DynamicProtoChangeDetector(null).instantiate(view, []);
view.init(cd, [], [], [], [], [], [], []); view.init(cd, [], [], [], [], [], [], [], [], []);
return view; return view;
} }
@ -48,7 +48,7 @@ class HydrateAwareFakeView {
return this.isHydrated; return this.isHydrated;
} }
hydrate(_, __, ___) { hydrate(_, __, ___, ____) {
this.isHydrated = true; this.isHydrated = true;
} }
@ -97,7 +97,7 @@ export function main() {
} }
beforeEach(() => { beforeEach(() => {
viewContainer.hydrate(new Injector([]), null); viewContainer.hydrate(new Injector([]), null, null);
var fillerView = createView([el('<filler>filler</filler>')]); var fillerView = createView([el('<filler>filler</filler>')]);
viewContainer.insert(fillerView); viewContainer.insert(fillerView);
}); });
@ -213,11 +213,11 @@ export function main() {
var fancyView; var fancyView;
beforeEach(() => { beforeEach(() => {
var parser = new Parser(new Lexer()); var parser = new Parser(new Lexer());
viewContainer.hydrate(new Injector([]), null); viewContainer.hydrate(new Injector([]), null, null);
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'), var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null)); new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null));
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective])); pv.bindElement(null, 0, new ProtoElementInjector(null, 1, [SomeDirective]));
pv.bindTextNode(0, parser.parseBinding('foo', null)); pv.bindTextNode(0, parser.parseBinding('foo', null));
fancyView = pv.instantiate(null, null); fancyView = pv.instantiate(null, null);
}); });

View File

@ -46,7 +46,7 @@ export function main() {
function createView(protoView, eventManager: EventManager = null) { function createView(protoView, eventManager: EventManager = null) {
var ctx = new MyEvaluationContext(); var ctx = new MyEvaluationContext();
var view = protoView.instantiate(null, eventManager); var view = protoView.instantiate(null, eventManager);
view.hydrate(null, null, ctx); view.hydrate(null, null, null, ctx);
return view; return view;
} }
@ -69,7 +69,7 @@ export function main() {
it('should be able to be hydrated and dehydrated', () => { it('should be able to be hydrated and dehydrated', () => {
var ctx = new Object(); var ctx = new Object();
view.hydrate(null, null, ctx); view.hydrate(null, null, null, ctx);
expect(view.hydrated()).toBe(true); expect(view.hydrated()).toBe(true);
view.dehydrate(); view.dehydrate();
@ -78,7 +78,7 @@ export function main() {
it('should hydrate and dehydrate the change detector', () => { it('should hydrate and dehydrate the change detector', () => {
var ctx = new Object(); var ctx = new Object();
view.hydrate(null, null, ctx); view.hydrate(null, null, null, ctx);
expect(view.changeDetector.hydrated()).toBe(true); expect(view.changeDetector.hydrated()).toBe(true);
view.dehydrate(); view.dehydrate();
@ -114,7 +114,7 @@ export function main() {
it('when dehydrated should set locals to null', () => { it('when dehydrated should set locals to null', () => {
view.setLocal('context-foo', 'bar'); view.setLocal('context-foo', 'bar');
view.dehydrate(); view.dehydrate();
view.hydrate(null, null, new Object()); view.hydrate(null, null, null, new Object());
expect(view.context.get('template-foo')).toBe(null); expect(view.context.get('template-foo')).toBe(null);
}); });
@ -136,7 +136,7 @@ export function main() {
var pv = new ProtoView(templateAwareCreateElement('<div id="1"></div>'), var pv = new ProtoView(templateAwareCreateElement('<div id="1"></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.nodes.length).toBe(1); expect(view.nodes.length).toBe(1);
expect(DOM.getAttribute(view.nodes[0], 'id')).toEqual('1'); expect(DOM.getAttribute(view.nodes[0], 'id')).toEqual('1');
}); });
@ -146,11 +146,11 @@ export function main() {
it('should collect property bindings on the root element if it has the ng-binding class', () => { it('should collect property bindings on the root element if it has the ng-binding class', () => {
var pv = new ProtoView(templateAwareCreateElement('<div [prop]="a" class="ng-binding"></div>'), var pv = new ProtoView(templateAwareCreateElement('<div [prop]="a" class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(null); pv.bindElement(null, 0, null);
pv.bindElementProperty(parser.parseBinding('a', null), 'prop', reflector.setter('prop')); pv.bindElementProperty(parser.parseBinding('a', null), 'prop', reflector.setter('prop'));
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.bindElements.length).toEqual(1); expect(view.bindElements.length).toEqual(1);
expect(view.bindElements[0]).toBe(view.nodes[0]); expect(view.bindElements[0]).toBe(view.nodes[0]);
}); });
@ -158,11 +158,11 @@ export function main() {
it('should collect property bindings on child elements with ng-binding class', () => { it('should collect property bindings on child elements with ng-binding class', () => {
var pv = new ProtoView(templateAwareCreateElement('<div><span></span><span class="ng-binding"></span></div>'), var pv = new ProtoView(templateAwareCreateElement('<div><span></span><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(null); pv.bindElement(null, 0, null);
pv.bindElementProperty(parser.parseBinding('b', null), 'a', reflector.setter('a')); pv.bindElementProperty(parser.parseBinding('b', null), 'a', reflector.setter('a'));
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.bindElements.length).toEqual(1); expect(view.bindElements.length).toEqual(1);
expect(view.bindElements[0]).toBe(view.nodes[0].childNodes[1]); expect(view.bindElements[0]).toBe(view.nodes[0].childNodes[1]);
}); });
@ -174,12 +174,12 @@ export function main() {
it('should collect text nodes under the root element', () => { it('should collect text nodes under the root element', () => {
var pv = new ProtoView(templateAwareCreateElement('<div class="ng-binding">{{}}<span></span>{{}}</div>'), var pv = new ProtoView(templateAwareCreateElement('<div class="ng-binding">{{}}<span></span>{{}}</div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(null); pv.bindElement(null, 0, null);
pv.bindTextNode(0, parser.parseBinding('a', null)); pv.bindTextNode(0, parser.parseBinding('a', null));
pv.bindTextNode(2, parser.parseBinding('b', null)); pv.bindTextNode(2, parser.parseBinding('b', null));
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.textNodes.length).toEqual(2); expect(view.textNodes.length).toEqual(2);
expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[0]); expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[0]);
expect(view.textNodes[1]).toBe(view.nodes[0].childNodes[2]); expect(view.textNodes[1]).toBe(view.nodes[0].childNodes[2]);
@ -188,11 +188,11 @@ export function main() {
it('should collect text nodes with bindings on child elements with ng-binding class', () => { it('should collect text nodes with bindings on child elements with ng-binding class', () => {
var pv = new ProtoView(templateAwareCreateElement('<div><span> </span><span class="ng-binding">{{}}</span></div>'), var pv = new ProtoView(templateAwareCreateElement('<div><span> </span><span class="ng-binding">{{}}</span></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(null); pv.bindElement(null, 0, null);
pv.bindTextNode(0, parser.parseBinding('b', null)); pv.bindTextNode(0, parser.parseBinding('b', null));
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.textNodes.length).toEqual(1); expect(view.textNodes.length).toEqual(1);
expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[1].childNodes[0]); expect(view.textNodes[0]).toBe(view.nodes[0].childNodes[1].childNodes[0]);
}); });
@ -207,7 +207,7 @@ export function main() {
new NativeShadowDomStrategy(null)); new NativeShadowDomStrategy(null));
pv.instantiateInPlace = true; pv.instantiateInPlace = true;
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.nodes[0]).toBe(template); expect(view.nodes[0]).toBe(template);
}); });
@ -216,7 +216,7 @@ export function main() {
var pv = new ProtoView(template, new DynamicProtoChangeDetector(null), var pv = new ProtoView(template, new DynamicProtoChangeDetector(null),
new NativeShadowDomStrategy(null)) new NativeShadowDomStrategy(null))
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.nodes[0]).not.toBe(template); expect(view.nodes[0]).not.toBe(template);
}); });
}); });
@ -233,10 +233,10 @@ export function main() {
it('should use the directives of the ProtoElementInjector', () => { it('should use the directives of the ProtoElementInjector', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'), var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective])); pv.bindElement(null, 0, new ProtoElementInjector(null, 1, [SomeDirective]));
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.elementInjectors.length).toBe(1); expect(view.elementInjectors.length).toBe(1);
expect(view.elementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); expect(view.elementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true);
}); });
@ -245,11 +245,11 @@ export function main() {
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'), var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]); var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
pv.bindElement(protoParent); pv.bindElement(null, 0, protoParent);
pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective])); pv.bindElement(null, 0, new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.elementInjectors.length).toBe(2); expect(view.elementInjectors.length).toBe(2);
expect(view.elementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); expect(view.elementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true);
expect(view.elementInjectors[1].parent).toBe(view.elementInjectors[0]); expect(view.elementInjectors[1].parent).toBe(view.elementInjectors[0]);
@ -259,9 +259,9 @@ export function main() {
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'), var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]); var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
pv.bindElement(protoParent); pv.bindElement(null, 0, protoParent);
var testProtoElementInjector = new TestProtoElementInjector(protoParent, 1, [AnotherDirective]); var testProtoElementInjector = new TestProtoElementInjector(protoParent, 1, [AnotherDirective]);
pv.bindElement(testProtoElementInjector); pv.bindElement(null, 0, testProtoElementInjector);
var hostProtoInjector = new ProtoElementInjector(null, 0, []); var hostProtoInjector = new ProtoElementInjector(null, 0, []);
var hostInjector = hostProtoInjector.instantiate(null, null); var hostInjector = hostProtoInjector.instantiate(null, null);
@ -274,9 +274,9 @@ export function main() {
it('should pass the host injector when there is no parent injector', () => { it('should pass the host injector when there is no parent injector', () => {
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'), var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirective])); pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeDirective]));
var testProtoElementInjector = new TestProtoElementInjector(null, 1, [AnotherDirective]); var testProtoElementInjector = new TestProtoElementInjector(null, 1, [AnotherDirective]);
pv.bindElement(testProtoElementInjector); pv.bindElement(null, 0, testProtoElementInjector);
var hostProtoInjector = new ProtoElementInjector(null, 0, []); var hostProtoInjector = new ProtoElementInjector(null, 0, []);
var hostInjector = hostProtoInjector.instantiate(null, null); var hostInjector = hostProtoInjector.instantiate(null, null);
@ -292,11 +292,11 @@ export function main() {
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'), var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]); var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
pv.bindElement(protoParent); pv.bindElement(null, 0, protoParent);
pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective])); pv.bindElement(null, 0, new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.rootElementInjectors.length).toBe(1); expect(view.rootElementInjectors.length).toBe(1);
expect(view.rootElementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); expect(view.rootElementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true);
}); });
@ -304,11 +304,11 @@ export function main() {
it('should collect multiple root element injectors', () => { it('should collect multiple root element injectors', () => {
var pv = new ProtoView(el('<div><span class="ng-binding"></span><span class="ng-binding"></span></div>'), var pv = new ProtoView(el('<div><span class="ng-binding"></span><span class="ng-binding"></span></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective])); pv.bindElement(null, 0, new ProtoElementInjector(null, 1, [SomeDirective]));
pv.bindElement(new ProtoElementInjector(null, 2, [AnotherDirective])); pv.bindElement(null, 0, new ProtoElementInjector(null, 2, [AnotherDirective]));
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(null, null, null); view.hydrate(null, null, null, null);
expect(view.rootElementInjectors.length).toBe(2) expect(view.rootElementInjectors.length).toBe(2)
expect(view.rootElementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); expect(view.rootElementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true);
expect(view.rootElementInjectors[1].get(AnotherDirective) instanceof AnotherDirective).toBe(true); expect(view.rootElementInjectors[1].get(AnotherDirective) instanceof AnotherDirective).toBe(true);
@ -322,7 +322,7 @@ export function main() {
function createComponentWithSubPV(subProtoView) { function createComponentWithSubPV(subProtoView) {
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'), var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'),
new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null)); new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null));
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeComponent], true)); var binder = pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeComponent], true));
binder.componentDirective = someComponentDirective; binder.componentDirective = someComponentDirective;
binder.nestedProtoView = subProtoView; binder.nestedProtoView = subProtoView;
return pv; return pv;
@ -331,7 +331,7 @@ export function main() {
function createNestedView(protoView) { function createNestedView(protoView) {
ctx = new MyEvaluationContext(); ctx = new MyEvaluationContext();
var view = protoView.instantiate(null, null); var view = protoView.instantiate(null, null);
view.hydrate(new Injector([]), null, ctx); view.hydrate(new Injector([]), null, null, ctx);
return view; return view;
} }
@ -351,7 +351,7 @@ export function main() {
el('<div dec class="ng-binding">hello shadow dom</div>'), el('<div dec class="ng-binding">hello shadow dom</div>'),
new DynamicProtoChangeDetector(null), new DynamicProtoChangeDetector(null),
null); null);
subpv.bindElement( subpv.bindElement(null, 0,
new ProtoElementInjector(null, 0, [ServiceDependentDecorator])); new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
var pv = createComponentWithSubPV(subpv); var pv = createComponentWithSubPV(subpv);
@ -376,7 +376,7 @@ export function main() {
el('<div dec class="ng-binding">hello shadow dom</div>'), el('<div dec class="ng-binding">hello shadow dom</div>'),
new DynamicProtoChangeDetector(null), new DynamicProtoChangeDetector(null),
null); null);
subpv.bindElement( subpv.bindElement(null, 0,
new ProtoElementInjector(null, 0, [ServiceDependentDecorator])); new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
var pv = createComponentWithSubPV(subpv); var pv = createComponentWithSubPV(subpv);
@ -406,7 +406,7 @@ export function main() {
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'), var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'),
new DynamicProtoChangeDetector(null), new EmulatedScopedShadowDomStrategy(null, null, null)); new DynamicProtoChangeDetector(null), new EmulatedScopedShadowDomStrategy(null, null, null));
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeComponent], true)); var binder = pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeComponent], true));
binder.componentDirective = new DirectiveMetadataReader().read(SomeComponent); binder.componentDirective = new DirectiveMetadataReader().read(SomeComponent);
binder.nestedProtoView = subpv; binder.nestedProtoView = subpv;
@ -422,7 +422,7 @@ export function main() {
el('<div id="1"></div>'), new DynamicProtoChangeDetector(null), null); el('<div id="1"></div>'), new DynamicProtoChangeDetector(null), null);
var pv = new ProtoView(el('<someTmpl class="ng-binding"></someTmpl>'), var pv = new ProtoView(el('<someTmpl class="ng-binding"></someTmpl>'),
new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null)); new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(null));
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeViewport])); var binder = pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeViewport]));
binder.viewportDirective = someViewportDirective; binder.viewportDirective = someViewportDirective;
binder.nestedProtoView = templateProtoView; binder.nestedProtoView = templateProtoView;
@ -468,7 +468,7 @@ export function main() {
function createProtoView() { function createProtoView() {
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'), var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(new TestProtoElementInjector(null, 0, [])); pv.bindElement(null, 0, new TestProtoElementInjector(null, 0, []));
pv.bindEvent('click', parser.parseBinding('callMe($event)', null)); pv.bindEvent('click', parser.parseBinding('callMe($event)', null));
return pv; return pv;
} }
@ -503,7 +503,7 @@ export function main() {
it('should support custom event emitters', () => { it('should support custom event emitters', () => {
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'), var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(new TestProtoElementInjector(null, 0, [EventEmitterDirective])); pv.bindElement(null, 0, new TestProtoElementInjector(null, 0, [EventEmitterDirective]));
pv.bindEvent('click', parser.parseBinding('callMe($event)', null)); pv.bindEvent('click', parser.parseBinding('callMe($event)', null));
createViewAndContext(pv); createViewAndContext(pv);
@ -524,7 +524,7 @@ export function main() {
it('should bind to directive events', () => { it('should bind to directive events', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'), var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirectiveWithEventHandler])); pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeDirectiveWithEventHandler]));
pv.bindEvent('click', parser.parseAction('onEvent($event)', null), 0); pv.bindEvent('click', parser.parseAction('onEvent($event)', null), 0);
view = createView(pv, new EventManager([new DomEventsPlugin()], new FakeVmTurnZone())); view = createView(pv, new EventManager([new DomEventsPlugin()], new FakeVmTurnZone()));
@ -549,7 +549,7 @@ export function main() {
it('should consume text node changes', () => { it('should consume text node changes', () => {
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'), var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(null); pv.bindElement(null, 0, null);
pv.bindTextNode(0, parser.parseBinding('foo', null)); pv.bindTextNode(0, parser.parseBinding('foo', null));
createViewAndChangeDetector(pv); createViewAndChangeDetector(pv);
@ -561,7 +561,7 @@ export function main() {
it('should consume element binding changes', () => { it('should consume element binding changes', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'), var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(null); pv.bindElement(null, 0, null);
pv.bindElementProperty(parser.parseBinding('foo', null), 'id', reflector.setter('id')); pv.bindElementProperty(parser.parseBinding('foo', null), 'id', reflector.setter('id'));
createViewAndChangeDetector(pv); createViewAndChangeDetector(pv);
@ -573,7 +573,7 @@ export function main() {
it('should consume directive watch expression change', () => { it('should consume directive watch expression change', () => {
var pv = new ProtoView(el('<div class="ng-binding"></div>'), var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirective])); pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [SomeDirective]));
pv.bindDirectiveProperty(0, parser.parseBinding('foo', null), 'prop', reflector.setter('prop')); pv.bindDirectiveProperty(0, parser.parseBinding('foo', null), 'prop', reflector.setter('prop'));
createViewAndChangeDetector(pv); createViewAndChangeDetector(pv);
@ -586,7 +586,7 @@ export function main() {
var pv = new ProtoView(el('<div class="ng-binding"></div>'), var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(new ProtoElementInjector(null, 0, [ pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [
DirectiveBinding.createFromType(DirectiveImplementingOnChange, new Directive({lifecycle: [onChange]})) DirectiveBinding.createFromType(DirectiveImplementingOnChange, new Directive({lifecycle: [onChange]}))
])); ]));
pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a')); pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a'));
@ -605,7 +605,7 @@ export function main() {
var pv = new ProtoView(el('<div class="ng-binding"></div>'), var pv = new ProtoView(el('<div class="ng-binding"></div>'),
new DynamicProtoChangeDetector(null), null); new DynamicProtoChangeDetector(null), null);
pv.bindElement(new ProtoElementInjector(null, 0, [ pv.bindElement(null, 0, new ProtoElementInjector(null, 0, [
DirectiveBinding.createFromType(DirectiveImplementingOnChange, new Directive({lifecycle: [onChange]})) DirectiveBinding.createFromType(DirectiveImplementingOnChange, new Directive({lifecycle: [onChange]}))
])); ]));
pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a')); pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a'));
@ -643,7 +643,7 @@ export function main() {
someComponentDirective, new DynamicProtoChangeDetector(null), someComponentDirective, new DynamicProtoChangeDetector(null),
new NativeShadowDomStrategy(null)); new NativeShadowDomStrategy(null));
var view = rootProtoView.instantiate(null, null); var view = rootProtoView.instantiate(null, null);
view.hydrate(new Injector([]), null, null); view.hydrate(new Injector([]), null, null, null);
expect(view.rootElementInjectors[0].get(SomeComponent)).not.toBe(null); expect(view.rootElementInjectors[0].get(SomeComponent)).not.toBe(null);
}); });
@ -652,7 +652,7 @@ export function main() {
someComponentDirective, new DynamicProtoChangeDetector(null), someComponentDirective, new DynamicProtoChangeDetector(null),
new NativeShadowDomStrategy(null)); new NativeShadowDomStrategy(null));
var view = rootProtoView.instantiate(null, null); var view = rootProtoView.instantiate(null, null);
view.hydrate(new Injector([]), null, null); view.hydrate(new Injector([]), null, null, null);
expect(element.shadowRoot.childNodes[0].childNodes[0].nodeValue).toEqual('hi'); expect(element.shadowRoot.childNodes[0].childNodes[0].nodeValue).toEqual('hi');
}); });
}); });

View File

@ -45,7 +45,7 @@ export function main() {
function createView(pv) { function createView(pv) {
component = new TestComponent(); component = new TestComponent();
view = pv.instantiate(null, null); view = pv.instantiate(null, null);
view.hydrate(new Injector([]), null, component); view.hydrate(new Injector([]), null, null, component);
cd = view.changeDetector; cd = view.changeDetector;
} }

View File

@ -57,7 +57,7 @@ export function main() {
function createView(pv) { function createView(pv) {
component = new TestComponent(); component = new TestComponent();
view = pv.instantiate(null, null); view = pv.instantiate(null, null);
view.hydrate(new Injector([]), null, component); view.hydrate(new Injector([]), null, null, component);
cd = view.changeDetector; cd = view.changeDetector;
} }

View File

@ -54,7 +54,7 @@ export function main() {
function createView(pv) { function createView(pv) {
component = new TestComponent(); component = new TestComponent();
view = pv.instantiate(null, null); view = pv.instantiate(null, null);
view.hydrate(new Injector([]), null, component); view.hydrate(new Injector([]), null, null, component);
cd = view.changeDetector; cd = view.changeDetector;
} }

View File

@ -51,7 +51,7 @@ export function main() {
function createView(pv) { function createView(pv) {
component = new TestComponent(); component = new TestComponent();
view = pv.instantiate(null, null); view = pv.instantiate(null, null);
view.hydrate(new Injector([]), null, component); view.hydrate(new Injector([]), null, null, component);
cd = view.changeDetector; cd = view.changeDetector;
} }

View File

@ -63,7 +63,7 @@ export function main() {
compiler.compile(componentType).then((pv) => { compiler.compile(componentType).then((pv) => {
var view = pv.instantiate(null, null); var view = pv.instantiate(null, null);
view.hydrate(new Injector([]), null, context); view.hydrate(new Injector([]), null, null, context);
detectChanges(view); detectChanges(view);
callback(view); callback(view);
}); });