From 70c875ee14aff4f58f888e15cee26821a8ce9350 Mon Sep 17 00:00:00 2001 From: Yegor Jbanov Date: Mon, 16 Mar 2015 11:31:58 -0700 Subject: [PATCH] refactor(shadow dom): do not use injectors nor directives This prepares us for the app/render split in the compiler. --- modules/angular2/src/core/application.js | 2 +- .../angular2/src/core/compiler/compiler.js | 13 +- .../src/core/compiler/element_binder.js | 15 ++ .../src/core/compiler/element_injector.js | 16 +- .../core/compiler/pipeline/compile_element.js | 6 +- .../core/compiler/pipeline/default_steps.js | 7 +- .../compiler/pipeline/directive_parser.js | 3 +- .../pipeline/element_binder_builder.js | 20 ++- .../pipeline/element_binding_marker.js | 3 +- .../shadow_dom_emulation/content_tag.js | 35 +--- .../shadow_dom_emulation/light_dom.js | 72 +++++---- .../src/core/compiler/shadow_dom_strategy.js | 66 ++++++-- modules/angular2/src/core/compiler/view.js | 73 +++++---- .../src/core/compiler/view_container.js | 6 +- modules/angular2/src/facade/lang.es6 | 4 + .../core/compiler/compiler_common_tests.js | 8 +- .../core/compiler/element_injector_spec.js | 37 +---- .../test/core/compiler/integration_spec.js | 5 +- .../pipeline/element_binder_builder_spec.js | 2 +- .../pipeline/proto_view_builder_spec.js | 2 +- .../compiler/shadow_dom/content_tag_spec.js | 35 ++-- .../compiler/shadow_dom/light_dom_spec.js | 150 ++++++++---------- .../shadow_dom_emulation_integration_spec.js | 14 +- .../core/compiler/shadow_dom_strategy_spec.js | 4 - .../test/core/compiler/view_container_spec.js | 10 +- .../angular2/test/core/compiler/view_spec.js | 92 +++++------ .../angular2/test/directives/foreach_spec.js | 2 +- modules/angular2/test/directives/if_spec.js | 2 +- .../test/directives/non_bindable_spec.js | 2 +- .../angular2/test/directives/switch_spec.js | 2 +- .../angular2/test/forms/integration_spec.js | 2 +- 31 files changed, 367 insertions(+), 343 deletions(-) diff --git a/modules/angular2/src/core/application.js b/modules/angular2/src/core/application.js index fc8cff2735..5eef459146 100644 --- a/modules/angular2/src/core/application.js +++ b/modules/angular2/src/core/application.js @@ -67,7 +67,7 @@ function _injectorBindings(appComponentType): List { // the angular application. Thus the context and lightDomInjector are // empty. var view = appProtoView.instantiate(null, eventManager); - view.hydrate(injector, null, new Object()); + view.hydrate(injector, null, null, new Object()); return view; }); }, [ChangeDetection, Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken, diff --git a/modules/angular2/src/core/compiler/compiler.js b/modules/angular2/src/core/compiler/compiler.js index d8a2eab95b..969aa81080 100644 --- a/modules/angular2/src/core/compiler/compiler.js +++ b/modules/angular2/src/core/compiler/compiler.js @@ -11,7 +11,6 @@ import {CompileElement} from './pipeline/compile_element'; import {createDefaultSteps} from './pipeline/default_steps'; import {TemplateLoader} from './template_loader'; import {TemplateResolver} from './template_resolver'; -import {DirectiveMetadata} from './directive_metadata'; import {Template} from '../annotations/template'; import {ShadowDomStrategy} from './shadow_dom_strategy'; import {CompileStep} from './pipeline/compile_step'; @@ -56,7 +55,6 @@ export class Compiler { _templateLoader:TemplateLoader; _compiling:Map; _shadowDomStrategy: ShadowDomStrategy; - _shadowDomDirectives: List; _templateResolver: TemplateResolver; _componentUrlMapper: ComponentUrlMapper; _urlResolver: UrlResolver; @@ -80,11 +78,6 @@ export class Compiler { this._templateLoader = templateLoader; this._compiling = MapWrapper.create(); 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._componentUrlMapper = componentUrlMapper; this._urlResolver = urlResolver; @@ -93,12 +86,8 @@ export class Compiler { } createSteps(component:Type, template: Template):List { - // Merge directive metadata (from the template and from the shadow dom strategy) - var dirMetadata = []; - var tplMetadata = ListWrapper.map(this._flattenDirectives(template), + var dirMetadata = ListWrapper.map(this._flattenDirectives(template), (d) => this._reader.read(d)); - dirMetadata = ListWrapper.concat(dirMetadata, tplMetadata); - dirMetadata = ListWrapper.concat(dirMetadata, this._shadowDomDirectives); var cmpMetadata = this._reader.read(component); diff --git a/modules/angular2/src/core/compiler/element_binder.js b/modules/angular2/src/core/compiler/element_binder.js index eb4bce90a5..948fec7e41 100644 --- a/modules/angular2/src/core/compiler/element_binder.js +++ b/modules/angular2/src/core/compiler/element_binder.js @@ -1,3 +1,4 @@ +import {int, isBlank, BaseException} from 'angular2/src/facade/lang'; import {ProtoElementInjector} from './element_injector'; import {DirectiveMetadata} from './directive_metadata'; import {List, StringMap} from 'angular2/src/facade/collection'; @@ -11,12 +12,24 @@ export class ElementBinder { hasElementPropertyBindings:boolean; nestedProtoView: ProtoView; events:StringMap; + contentTagSelector:string; + parent:ElementBinder; + index:int; + distanceToParent:int; constructor( + index:int, parent:ElementBinder, distanceToParent: int, protoElementInjector: ProtoElementInjector, componentDirective:DirectiveMetadata, viewportDirective:DirectiveMetadata) { + if (isBlank(index)) { + throw new BaseException('null index not allowed.'); + } + this.protoElementInjector = protoElementInjector; this.componentDirective = componentDirective; this.viewportDirective = viewportDirective; + this.parent = parent; + this.index = index; + this.distanceToParent = distanceToParent; // updated later when events are bound this.events = null; // updated later when text nodes are bound @@ -25,5 +38,7 @@ export class ElementBinder { this.hasElementPropertyBindings = false; // updated later, so we are able to resolve cycles this.nestedProtoView = null; + // updated later in the compilation pipeline + this.contentTagSelector = null; } } diff --git a/modules/angular2/src/core/compiler/element_injector.js b/modules/angular2/src/core/compiler/element_injector.js index dd3a344526..c667a45007 100644 --- a/modules/angular2/src/core/compiler/element_injector.js +++ b/modules/angular2/src/core/compiler/element_injector.js @@ -5,7 +5,6 @@ import {Injector, Key, Dependency, bind, Binding, NoProviderError, ProviderError import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility'; import {EventEmitter, PropertySetter} from 'angular2/src/core/annotations/di'; 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 {NgElement} from 'angular2/src/core/dom/element'; import {Directive, onChange, onDestroy} from 'angular2/src/core/annotations/annotations' @@ -24,8 +23,6 @@ class StaticKeys { viewId:number; ngElementId:number; viewContainerId:number; - destinationLightDomId:number; - lightDomId:number; bindingPropagationConfigId:number; constructor() { @@ -33,8 +30,6 @@ class StaticKeys { this.viewId = Key.get(viewModule.View).id; this.ngElementId = Key.get(NgElement).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; } @@ -166,14 +161,12 @@ export class PreBuiltObjects { view:viewModule.View; element:NgElement; viewContainer:ViewContainer; - lightDom:LightDom; bindingPropagationConfig:BindingPropagationConfig; - constructor(view, element:NgElement, viewContainer:ViewContainer, lightDom:LightDom, + constructor(view, element:NgElement, viewContainer:ViewContainer, bindingPropagationConfig:BindingPropagationConfig) { this.view = view; this.element = element; this.viewContainer = viewContainer; - this.lightDom = lightDom; this.bindingPropagationConfig = bindingPropagationConfig; } } @@ -577,13 +570,6 @@ export class ElementInjector extends TreeNode { if (keyId === staticKeys.ngElementId) return this._preBuiltObjects.element; if (keyId === staticKeys.viewContainerId) return this._preBuiltObjects.viewContainer; 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 return _undefined; diff --git a/modules/angular2/src/core/compiler/pipeline/compile_element.js b/modules/angular2/src/core/compiler/pipeline/compile_element.js index 0b07ba0b9d..be3e84214b 100644 --- a/modules/angular2/src/core/compiler/pipeline/compile_element.js +++ b/modules/angular2/src/core/compiler/pipeline/compile_element.js @@ -36,10 +36,12 @@ export class CompileElement { inheritedProtoView:ProtoView; inheritedProtoElementInjector:ProtoElementInjector; inheritedElementBinder:ElementBinder; - distanceToParentInjector:number; + distanceToParentInjector:int; + distanceToParentBinder:int; compileChildren: boolean; ignoreBindings: boolean; elementDescription: string; // e.g. '
' : used to provide context in case of error + contentTagSelector: string; constructor(element, compilationUnit = '') { this.element = element; @@ -65,9 +67,11 @@ export class CompileElement { // an own elementBinder this.inheritedElementBinder = null; this.distanceToParentInjector = 0; + this.distanceToParentBinder = 0; this.compileChildren = true; // set to true to ignore all the bindings on the element this.ignoreBindings = false; + this.contentTagSelector = null; // description is calculated here as compilation steps may change the element var tplDesc = assertionsEnabled()? getElementDescription(element) : null; if (compilationUnit !== '') { diff --git a/modules/angular2/src/core/compiler/pipeline/default_steps.js b/modules/angular2/src/core/compiler/pipeline/default_steps.js index adf4f2926e..096b593ee3 100644 --- a/modules/angular2/src/core/compiler/pipeline/default_steps.js +++ b/modules/angular2/src/core/compiler/pipeline/default_steps.js @@ -1,6 +1,5 @@ import {ChangeDetection, Parser} from 'angular2/change_detection'; import {List, ListWrapper} from 'angular2/src/facade/collection'; -import {isPresent} from 'angular2/src/facade/lang'; import {PropertyBindingParser} from './property_binding_parser'; import {TextInterpolationParser} from './text_interpolation_parser'; @@ -32,6 +31,7 @@ export function createDefaultSteps( var steps = [ new ViewSplitter(parser), cssProcessor.getCompileStep(compiledComponent, shadowDomStrategy, templateUrl), + shadowDomStrategy.getTemplateCompileStep(compiledComponent), new PropertyBindingParser(parser), new DirectiveParser(directives), new TextInterpolationParser(parser), @@ -41,10 +41,5 @@ export function createDefaultSteps( new ElementBinderBuilder(parser), ]; - var shadowDomStep = shadowDomStrategy.getTemplateCompileStep(compiledComponent); - if (isPresent(shadowDomStep)) { - ListWrapper.push(steps, shadowDomStep); - } - return steps; } diff --git a/modules/angular2/src/core/compiler/pipeline/directive_parser.js b/modules/angular2/src/core/compiler/pipeline/directive_parser.js index 3b324b35e7..742079bfc0 100644 --- a/modules/angular2/src/core/compiler/pipeline/directive_parser.js +++ b/modules/angular2/src/core/compiler/pipeline/directive_parser.js @@ -49,7 +49,8 @@ export class DirectiveParser extends CompileStep { var classList = current.classList(); 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++) { cssSelector.addClassName(classList[i]); } diff --git a/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js b/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js index 2df75ec375..790105261b 100644 --- a/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js +++ b/modules/angular2/src/core/compiler/pipeline/element_binder_builder.js @@ -135,6 +135,11 @@ export class ElementBinderBuilder extends CompileStep { process(parent:CompileElement, current:CompileElement, control:CompileControl) { var elementBinder = null; + var parentElementBinder = null; + var distanceToParentBinder = this._getDistanceToParentBinder(parent, current); + if (isPresent(parent)) { + parentElementBinder = parent.inheritedElementBinder; + } if (current.hasBindings) { var protoView = current.inheritedProtoView; var protoInjectorWasBuilt = isBlank(parent) ? true : @@ -143,8 +148,9 @@ export class ElementBinderBuilder extends CompileStep { var currentProtoElementInjector = protoInjectorWasBuilt ? current.inheritedProtoElementInjector : null; - elementBinder = protoView.bindElement(currentProtoElementInjector, - current.componentDirective, current.viewportDirective); + elementBinder = protoView.bindElement(parentElementBinder, distanceToParentBinder, + currentProtoElementInjector, current.componentDirective, current.viewportDirective); + current.distanceToParentBinder = 0; if (isPresent(current.textNodeBindings)) { this._bindTextNodes(protoView, current); @@ -155,15 +161,23 @@ export class ElementBinderBuilder extends CompileStep { if (isPresent(current.eventBindings)) { this._bindEvents(protoView, current); } + if (isPresent(current.contentTagSelector)) { + elementBinder.contentTagSelector = current.contentTagSelector; + } var directives = current.getAllDirectives(); this._bindDirectiveProperties(directives, current); this._bindDirectiveEvents(directives, current); } else if (isPresent(parent)) { - elementBinder = parent.inheritedElementBinder; + elementBinder = parentElementBinder; + current.distanceToParentBinder = distanceToParentBinder; } current.inheritedElementBinder = elementBinder; } + _getDistanceToParentBinder(parent, current) { + return isPresent(parent) ? parent.distanceToParentBinder + 1 : 0; + } + _bindTextNodes(protoView, compileElement) { MapWrapper.forEach(compileElement.textNodeBindings, (expression, indexInParent) => { protoView.bindTextNode(indexInParent, expression); diff --git a/modules/angular2/src/core/compiler/pipeline/element_binding_marker.js b/modules/angular2/src/core/compiler/pipeline/element_binding_marker.js index 8cf51bd4d4..461cff1322 100644 --- a/modules/angular2/src/core/compiler/pipeline/element_binding_marker.js +++ b/modules/angular2/src/core/compiler/pipeline/element_binding_marker.js @@ -37,7 +37,8 @@ export class ElementBindingMarker extends CompileStep { (isPresent(current.eventBindings) && MapWrapper.size(current.eventBindings)>0) || (isPresent(current.decoratorDirectives) && current.decoratorDirectives.length > 0) || isPresent(current.viewportDirective) || - isPresent(current.componentDirective); + isPresent(current.componentDirective) || + isPresent(current.contentTagSelector); if (hasBindings) { var element = current.element; diff --git a/modules/angular2/src/core/compiler/shadow_dom_emulation/content_tag.js b/modules/angular2/src/core/compiler/shadow_dom_emulation/content_tag.js index bc842cb6ef..b19be0adbd 100644 --- a/modules/angular2/src/core/compiler/shadow_dom_emulation/content_tag.js +++ b/modules/angular2/src/core/compiler/shadow_dom_emulation/content_tag.js @@ -1,10 +1,7 @@ -import {Decorator} from '../../annotations/annotations'; import * as ldModule from './light_dom'; -import {Inject} from 'angular2/di'; import {DOM} from 'angular2/src/dom/dom_adapter'; import {isPresent} from 'angular2/src/facade/lang'; import {List, ListWrapper} from 'angular2/src/facade/collection'; -import {NgElement} from 'angular2/src/core/dom/element'; class ContentStrategy { nodes:List; @@ -17,23 +14,16 @@ class ContentStrategy { * and thus does not affect redistribution. */ class RenderedContent extends ContentStrategy { - static _lazyScriptTemplate; beginScript; endScript; constructor(contentEl) { super(); - this._replaceContentElementWithScriptTags(contentEl); + this.beginScript = contentEl; + this.endScript = DOM.nextSibling(this.beginScript); 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. // Previous content is removed. insert(nodes:List) { @@ -42,16 +32,6 @@ class RenderedContent extends ContentStrategy { 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) { var p = DOM.parentElement(this.beginScript); for (var next = DOM.nextSibling(this.beginScript); @@ -83,18 +63,17 @@ class IntermediateContent extends ContentStrategy { } -@Decorator({ - selector: 'content' -}) export class Content { select:string; _strategy:ContentStrategy; + contentStartElement; - constructor(@Inject(ldModule.DestinationLightDom) destinationLightDom, contentEl:NgElement) { - this.select = contentEl.getAttribute('select'); + constructor(destinationLightDom:ldModule.LightDom, contentStartEl, selector:string) { + this.select = selector; + this.contentStartElement = contentStartEl; this._strategy = isPresent(destinationLightDom) ? new IntermediateContent(destinationLightDom) : - new RenderedContent(contentEl.domElement); + new RenderedContent(contentStartEl); } nodes():List { diff --git a/modules/angular2/src/core/compiler/shadow_dom_emulation/light_dom.js b/modules/angular2/src/core/compiler/shadow_dom_emulation/light_dom.js index c04bec3331..82a915ae4e 100644 --- a/modules/angular2/src/core/compiler/shadow_dom_emulation/light_dom.js +++ b/modules/angular2/src/core/compiler/shadow_dom_emulation/light_dom.js @@ -3,8 +3,6 @@ import {List, ListWrapper} from 'angular2/src/facade/collection'; import {isBlank, isPresent} from 'angular2/src/facade/lang'; import * as viewModule from '../view'; -import {ElementInjector} from '../element_injector'; -import {ViewContainer} from '../view_container'; import {Content} from './content_tag'; export class DestinationLightDom {} @@ -12,11 +10,13 @@ export class DestinationLightDom {} class _Root { node; - injector:ElementInjector; + viewContainer; + content; - constructor(node, injector) { + constructor(node, viewContainer, content) { this.node = node; - this.injector = injector; + this.viewContainer = viewContainer; + this.content = content; } } @@ -52,19 +52,18 @@ export class LightDom { // Collects the Content directives from the view and all its child views _collectAllContentTags(view: viewModule.View, acc:List):List { - var eis = view.elementInjectors; - for (var i = 0; i < eis.length; ++i) { - var ei = eis[i]; - if (isBlank(ei)) continue; - - if (ei.hasDirective(Content)) { - ListWrapper.push(acc, ei.get(Content)); - - } else if (ei.hasPreBuiltObject(ViewContainer)) { - var vc = ei.get(ViewContainer); + var contentTags = view.contentTags; + var vcs = view.viewContainers; + for (var i=0; i { this._collectAllContentTags(view, acc); - }); + }); } } return acc; @@ -76,21 +75,16 @@ export class LightDom { // - plain DOM nodes expandedDomNodes():List { var res = []; - + var roots = this._roots(); for (var i = 0; i < roots.length; ++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 { ListWrapper.push(res, root.node); } @@ -103,10 +97,24 @@ export class LightDom { _roots() { if (isPresent(this.roots)) return this.roots; - var viewInj = this.lightDomView.elementInjectors; - this.roots = ListWrapper.map(this.nodes, (n) => - new _Root(n, ListWrapper.find(viewInj, - (inj) => isPresent(inj) ? inj.forElement(n) : false))); + var viewContainers = this.lightDomView.viewContainers; + var contentTags = this.lightDomView.contentTags; + + this.roots = ListWrapper.map(this.nodes, (n) => { + var foundVc = null; + var foundContentTag = null; + for (var i=0; i, nodes:List) { var select = content.select; var matchSelector = (n) => DOM.elementMatches(n, select); - if (isBlank(select)) { + // Empty selector is identical to + if (select.length === 0) { content.insert(nodes); ListWrapper.clear(nodes); - } else { var matchingNodes = ListWrapper.filter(nodes, matchSelector); content.insert(matchingNodes); diff --git a/modules/angular2/src/core/compiler/shadow_dom_strategy.js b/modules/angular2/src/core/compiler/shadow_dom_strategy.js index d1748985bd..c291751a9a 100644 --- a/modules/angular2/src/core/compiler/shadow_dom_strategy.js +++ b/modules/angular2/src/core/compiler/shadow_dom_strategy.js @@ -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 {PromiseWrapper} from 'angular2/src/facade/async'; @@ -6,7 +6,6 @@ import {DOM} from 'angular2/src/dom/dom_adapter'; import * as viewModule from './view'; -import {Content} from './shadow_dom_emulation/content_tag'; import {LightDom} from './shadow_dom_emulation/light_dom'; 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 {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 { attachTemplate(el, view:viewModule.View) {} constructLightDom(lightDomView:viewModule.View, shadowDomView:viewModule.View, el): LightDom { return null; } - polyfillDirectives():List { return []; } /** * An optional step that can modify the template style elements. * * @param {DirectiveMetadata} cmpMetadata * @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 { - 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. * * @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. @@ -87,14 +96,14 @@ export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy { return new LightDom(lightDomView, shadowDomView, el); } - polyfillDirectives():List { - return [Content]; - } - getStyleCompileStep(cmpMetadata: DirectiveMetadata, templateUrl: string): NS.CompileStep { return new _EmulatedUnscopedCssStep(cmpMetadata, templateUrl, this._styleUrlResolver, 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; constructor(cmpMetadata: DirectiveMetadata) { @@ -167,6 +208,7 @@ class _ShimShadowDomStep extends NS.CompileStep { process(parent:CompileElement, current:CompileElement, control:CompileControl) { + super.process(parent, current, control); if (current.ignoreBindings) { return; } diff --git a/modules/angular2/src/core/compiler/view.js b/modules/angular2/src/core/compiler/view.js index 1092f7fe2e..8c09e9eca1 100644 --- a/modules/angular2/src/core/compiler/view.js +++ b/modules/angular2/src/core/compiler/view.js @@ -13,7 +13,8 @@ import {IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'angular2/src/f import {Injector} from 'angular2/di'; import {NgElement} from 'angular2/src/core/dom/element'; 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 {ViewPool} from './view_pool'; import {EventManager} from 'angular2/src/core/events/event_manager'; @@ -41,7 +42,9 @@ export class View { nodes:List; componentChildViews: List; viewContainers: List; + contentTags: List; preBuiltObjects: List; + lightDoms: List; proto: ProtoView; context: any; contextWithLocals:ContextWithVariableBindings; @@ -56,7 +59,9 @@ export class View { this.bindElements = null; this.componentChildViews = null; this.viewContainers = null; + this.contentTags = null; this.preBuiltObjects = null; + this.lightDoms = null; this.context = null; this.contextWithLocals = (MapWrapper.size(protoContextLocals) > 0) ? new ContextWithVariableBindings(null, MapWrapper.clone(protoContextLocals)) @@ -64,15 +69,17 @@ export class View { } 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) { this.changeDetector = changeDetector; this.elementInjectors = elementInjectors; this.rootElementInjectors = rootElementInjectors; this.textNodes = textNodes; this.bindElements = bindElements; this.viewContainers = viewContainers; + this.contentTags = contentTags; this.preBuiltObjects = preBuiltObjects; this.componentChildViews = componentChildViews; + this.lightDoms = lightDoms; } 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 * tree. */ - hydrate(appInjector: Injector, hostElementInjector: ElementInjector, + hydrate(appInjector: Injector, hostElementInjector: ElementInjector, hostLightDom: LightDom, context: Object) { if (this.hydrated()) throw new BaseException('The view is already hydrated.'); this._hydrateContext(context); // viewContainers 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; @@ -171,18 +181,14 @@ export class View { if (isPresent(componentDirective)) { 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 < binders.length; ++i) { - var componentDirective = binders[i].componentDirective; - if (isPresent(componentDirective)) { - var lightDom = this.preBuiltObjects[i].lightDom; - if (isPresent(lightDom)) { - lightDom.redistribute(); - } + for (var i = 0; i < this.lightDoms.length; ++i) { + var lightDom = this.lightDoms[i]; + if (isPresent(lightDom)) { + lightDom.redistribute(); } } } @@ -205,7 +211,10 @@ export class View { // viewContainers if (isPresent(this.viewContainers)) { 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 elementsWithPropertyBindings = []; var preBuiltObjects = ListWrapper.createFixedSize(binders.length); - var viewContainers = []; + var viewContainers = ListWrapper.createFixedSize(binders.length); + var contentTags = ListWrapper.createFixedSize(binders.length); var componentChildViews = []; + var lightDoms = ListWrapper.createFixedSize(binders.length); for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) { var binder = binders[binderIdx]; @@ -427,20 +438,32 @@ export class ProtoView { ListWrapper.push(componentChildViews, childView); } + lightDoms[binderIdx] = lightDom; + + var destLightDom = null; + if (isPresent(binder.parent) && binder.distanceToParent === 1) { + destLightDom = lightDoms[binder.parent.index]; + } // viewContainers var viewContainer = null; if (isPresent(binder.viewportDirective)) { - var destLightDom = this._directParentElementLightDom(protoElementInjector, preBuiltObjects); viewContainer = new ViewContainer(view, element, binder.nestedProtoView, elementInjector, 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 if (isPresent(elementInjector)) { preBuiltObjects[binderIdx] = new PreBuiltObjects(view, new NgElement(element), viewContainer, - lightDom, bindingPropagationConfig); + bindingPropagationConfig); } // events @@ -460,7 +483,7 @@ export class ProtoView { this.eventHandlers = eventHandlers; view.init(changeDetector, elementInjectors, rootElementInjectors, textNodes, elementsWithPropertyBindings, - viewContainers, preBuiltObjects, componentChildViews); + viewContainers, contentTags, preBuiltObjects, componentChildViews, lightDoms); 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) { MapWrapper.set(this.variableBindings, contextName, templateName); MapWrapper.set(this.protoContextLocals, templateName, null); } - bindElement(protoElementInjector:ProtoElementInjector, + bindElement(parent:ElementBinder, distanceToParent:int, protoElementInjector:ProtoElementInjector, 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); return elBinder; } @@ -601,7 +620,7 @@ export class ProtoView { var cmpType = rootComponentAnnotatedType.type; var rootProtoView = new ProtoView(insertionElement, protoChangeDetector, shadowDomStrategy); rootProtoView.instantiateInPlace = true; - var binder = rootProtoView.bindElement( + var binder = rootProtoView.bindElement(null, 0, new ProtoElementInjector(null, 0, [cmpType], true)); binder.componentDirective = rootComponentAnnotatedType; binder.nestedProtoView = protoView; diff --git a/modules/angular2/src/core/compiler/view_container.js b/modules/angular2/src/core/compiler/view_container.js index a824a63af8..d79d602435 100644 --- a/modules/angular2/src/core/compiler/view_container.js +++ b/modules/angular2/src/core/compiler/view_container.js @@ -40,10 +40,10 @@ export class ViewContainer { this._eventManager = eventManager; } - hydrate(appInjector: Injector, hostElementInjector: eiModule.ElementInjector) { + hydrate(appInjector: Injector, hostElementInjector: eiModule.ElementInjector, hostLightDom: ldModule.LightDom) { this.appInjector = appInjector; this.hostElementInjector = hostElementInjector; - this.hostLightDom = isPresent(hostElementInjector) ? hostElementInjector.get(ldModule.LightDom) : null; + this.hostLightDom = hostLightDom; } dehydrate() { @@ -85,7 +85,7 @@ export class ViewContainer { var newView = this.defaultProtoView.instantiate(this.hostElementInjector, this._eventManager); // insertion must come before hydration so that element injector trees are attached. 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. if (isPresent(this.hostLightDom)) { diff --git a/modules/angular2/src/facade/lang.es6 b/modules/angular2/src/facade/lang.es6 index 1e9a0dd960..f86cfe110b 100644 --- a/modules/angular2/src/facade/lang.es6 +++ b/modules/angular2/src/facade/lang.es6 @@ -208,6 +208,10 @@ export class RegExpWrapper { return input.match(regExp.single); } static matcher(regExp, input) { + // Reset regex state for the case + // someone did not loop over all matches + // last time. + regExp.multiple.lastIndex = 0; return { re: regExp.multiple, input: input diff --git a/modules/angular2/test/core/compiler/compiler_common_tests.js b/modules/angular2/test/core/compiler/compiler_common_tests.js index 514aafee75..6c52476ea6 100644 --- a/modules/angular2/test/core/compiler/compiler_common_tests.js +++ b/modules/angular2/test/core/compiler/compiler_common_tests.js @@ -115,7 +115,7 @@ export function runCompilerCommonTests() { if (DOM.hasClass(current.element, 'nested')) { current.componentDirective = reader.read(NestedComponent); current.inheritedProtoView = parent.inheritedProtoView; - current.inheritedElementBinder = current.inheritedProtoView.bindElement(null); + current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null); } else { current.inheritedProtoView = new ProtoView(current.element, null, null); } @@ -148,7 +148,7 @@ export function runCompilerCommonTests() { var compiler = createCompiler( (parent, current, control) => { current.inheritedProtoView = new ProtoView(current.element, null, null); 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); ListWrapper.push(nestedElBinders, current.inheritedElementBinder); } @@ -164,7 +164,7 @@ export function runCompilerCommonTests() { it('should allow recursive components', inject([AsyncTestCompleter], (async) => { var compiler = createCompiler( (parent, current, control) => { 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); }); compiler.compile(RecursiveComponent).then( (protoView) => { @@ -193,7 +193,7 @@ export function runCompilerCommonTests() { if (DOM.hasClass(current.element, 'parent')) { current.componentDirective = reader.read(NestedComponent); current.inheritedProtoView = parent.inheritedProtoView; - current.inheritedElementBinder = current.inheritedProtoView.bindElement(null); + current.inheritedElementBinder = current.inheritedProtoView.bindElement(null, 0, null); } else { current.inheritedProtoView = new ProtoView(current.element, null, null); } diff --git a/modules/angular2/test/core/compiler/element_injector_spec.js b/modules/angular2/test/core/compiler/element_injector_spec.js index 2127b16629..dbb38e3e2b 100644 --- a/modules/angular2/test/core/compiler/element_injector_spec.js +++ b/modules/angular2/test/core/compiler/element_injector_spec.js @@ -113,7 +113,7 @@ class DirectiveWithDestroy { } 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) { var lookupName = (item) => @@ -283,7 +283,7 @@ export function main() { it("should instantiate directives that depend on pre built objects", function () { 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); }); @@ -420,52 +420,31 @@ export function main() { describe("pre built objects", function () { it("should return view", function () { 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); }); it("should return element", function () { 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); }); it('should return viewContainer', function () { 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); }); it('should return bindingPropagationConfig', function () { 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); }); - - 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', () => { @@ -476,7 +455,7 @@ export function main() { var pv = new ProtoView(null, null, null); pv.eventHandlers = [handlers]; 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); inj.get(NeedsEventEmitter).click(); expect(called).toEqual(true); @@ -494,7 +473,7 @@ export function main() { var div = el('
'); 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); inj.get(NeedsPropertySetter).setProp('foobar'); diff --git a/modules/angular2/test/core/compiler/integration_spec.js b/modules/angular2/test/core/compiler/integration_spec.js index 9b3cb76f6a..f74b19bd90 100644 --- a/modules/angular2/test/core/compiler/integration_spec.js +++ b/modules/angular2/test/core/compiler/integration_spec.js @@ -68,7 +68,7 @@ export function main() { function createView(pv) { ctx = new MyComp(); view = pv.instantiate(null, null); - view.hydrate(new Injector([]), null, ctx); + view.hydrate(new Injector([]), null, null, ctx); cd = view.changeDetector; } @@ -479,7 +479,8 @@ export function main() { createView(pv); 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'); expect(childComponent.myAncestor).toBeAnInstanceOf(SomeDirective); diff --git a/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js b/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js index 7693df4354..b379b02da1 100644 --- a/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js +++ b/modules/angular2/test/core/compiler/pipeline/element_binder_builder_spec.js @@ -83,7 +83,7 @@ export function main() { function instantiateView(protoView) { evalContext = new Context(); view = protoView.instantiate(null, null); - view.hydrate(new Injector([]), null, evalContext); + view.hydrate(new Injector([]), null, null, evalContext); changeDetector = view.changeDetector; } diff --git a/modules/angular2/test/core/compiler/pipeline/proto_view_builder_spec.js b/modules/angular2/test/core/compiler/pipeline/proto_view_builder_spec.js index 292c4d187e..82271cfffe 100644 --- a/modules/angular2/test/core/compiler/pipeline/proto_view_builder_spec.js +++ b/modules/angular2/test/core/compiler/pipeline/proto_view_builder_spec.js @@ -21,7 +21,7 @@ export function main() { if (isPresent(DOM.getAttribute(current.element, 'var-binding'))) { 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))]); } diff --git a/modules/angular2/test/core/compiler/shadow_dom/content_tag_spec.js b/modules/angular2/test/core/compiler/shadow_dom/content_tag_spec.js index 5c0a62c099..298f05d9bb 100644 --- a/modules/angular2/test/core/compiler/shadow_dom/content_tag_spec.js +++ b/modules/angular2/test/core/compiler/shadow_dom/content_tag_spec.js @@ -2,47 +2,46 @@ import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el, proxy} import {IMPLEMENTS} from 'angular2/src/facade/lang'; import {DOM} from 'angular2/src/dom/dom_adapter'; 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'; @proxy @IMPLEMENTS(LightDom) class DummyLightDom extends SpyObject {noSuchMethod(m){super.noSuchMethod(m)}} -var _script = ``; +var _scriptStart = ``; +var _scriptEnd = ``; export function main() { describe('Content', function() { - it("should insert the nodes", () => { - var parent = el("
"); - var content = DOM.firstChild(parent); + var parent; + var content; - var c = new Content(null, new NgElement(content)); + beforeEach(() => { + parent = el(`
${_scriptStart}${_scriptEnd}`); + content = DOM.firstChild(parent); + }); + + it("should insert the nodes", () => { + var c = new Content(null, content, ''); c.insert([el(""), el("")]) - expect(DOM.getInnerHTML(parent)).toEqual(`${_script}${_script}`); + expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}${_scriptEnd}`); }); it("should remove the nodes from the previous insertion", () => { - var parent = el("
"); - var content = DOM.firstChild(parent); - - var c = new Content(null, new NgElement(content)); + var c = new Content(null, content, ''); c.insert([el("")]); c.insert([el("")]); - expect(DOM.getInnerHTML(parent)).toEqual(`${_script}${_script}`); + expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}${_scriptEnd}`); }); it("should insert empty list", () => { - var parent = el("
"); - var content = DOM.firstChild(parent); - - var c = new Content(null, new NgElement(content)); + var c = new Content(null, content, ''); c.insert([el("")]); c.insert([]); - expect(DOM.getInnerHTML(parent)).toEqual(`${_script}${_script}`); + expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}${_scriptEnd}`); }); }); -} \ No newline at end of file +} diff --git a/modules/angular2/test/core/compiler/shadow_dom/light_dom_spec.js b/modules/angular2/test/core/compiler/shadow_dom/light_dom_spec.js index ab6dbdc582..a017a7d19d 100644 --- a/modules/angular2/test/core/compiler/shadow_dom/light_dom_spec.js +++ b/modules/angular2/test/core/compiler/shadow_dom/light_dom_spec.js @@ -1,56 +1,35 @@ 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 {DOM} from 'angular2/src/dom/dom_adapter'; 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 {View} from 'angular2/src/core/compiler/view'; 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 @IMPLEMENTS(View) class FakeView { - elementInjectors; + contentTags; + viewContainers; - constructor(elementInjectors = null) { - this.elementInjectors = elementInjectors; + constructor(containers = null) { + 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) { @@ -61,10 +40,12 @@ class FakeView { @proxy @IMPLEMENTS(ViewContainer) class FakeViewContainer { + templateElement; _nodes; _contentTagContainers; - constructor(nodes = null, views = null) { + constructor(templateEl, nodes = null, views = null) { + this.templateElement = templateEl; this._nodes = nodes; this._contentTagContainers = views; } @@ -88,8 +69,10 @@ class FakeViewContainer { class FakeContentTag { select; _nodes; + contentStartElement; - constructor(select = null, nodes = null) { + constructor(contentEl, select = '', nodes = null) { + this.contentStartElement = contentEl; this.select = select; this._nodes = nodes; } @@ -113,69 +96,66 @@ export function main() { var lightDomView; beforeEach(() => { - lightDomView = new FakeView([]); + lightDomView = new FakeView(); }); describe("contentTags", () => { it("should collect content tags from element injectors", () => { - var tag = new FakeContentTag(); - var shadowDomView = new FakeView([new FakeElementInjector(tag)]); + var tag = new FakeContentTag(el('')); + var shadowDomView = new FakeView([tag]); - var lightDom = new LightDom(lightDomView, shadowDomView, el("
")); + var lightDom = new LightDom(lightDomView, shadowDomView, + el("
")); expect(lightDom.contentTags()).toEqual([tag]); }); it("should collect content tags from ViewContainers", () => { - var tag = new FakeContentTag(); - var vp = new FakeViewContainer(null, [ - new FakeView([new FakeElementInjector(tag, null)]) + var tag = new FakeContentTag(el('')); + var vc = new FakeViewContainer(null, null, [ + new FakeView([tag]) ]); - - var shadowDomView = new FakeView([new FakeElementInjector(null, vp)]); - - var lightDom = new LightDom(lightDomView, shadowDomView, el("
")); + var shadowDomView = new FakeView([vc]); + var lightDom = new LightDom(lightDomView, shadowDomView, + el("
")); expect(lightDom.contentTags()).toEqual([tag]); }); }); - describe("expanded roots", () => { + describe("expandedDomNodes", () => { it("should contain root nodes", () => { var lightDomEl = el("
") var lightDom = new LightDom(lightDomView, new FakeView(), lightDomEl); expect(toHtml(lightDom.expandedDomNodes())).toEqual([""]); }); - it("should include ViewContainer nodes", () => { - var lightDomEl = el("
") - - var lightDomView = new FakeView([ - new FakeElementInjector( - null, - new FakeViewContainer([el("")]), - DOM.firstChild(lightDomEl))]); - + it("should include view container nodes", () => { + var lightDomEl = el("
"); var lightDom = new LightDom( - lightDomView, - new FakeView(), + new FakeView([ + new FakeViewContainer( + DOM.firstChild(lightDomEl), // template element + [el('')] // light DOM nodes of view container + ) + ]), + null, lightDomEl); expect(toHtml(lightDom.expandedDomNodes())).toEqual([""]); }); it("should include content nodes", () => { - var lightDomEl = el("
") - - var lightDomView = new FakeView([ - new FakeElementInjector( - new FakeContentTag(null, [el("")]), - null, - DOM.firstChild(lightDomEl))]); - + var lightDomEl = el("
"); var lightDom = new LightDom( - lightDomView, - new FakeView(), + new FakeView([ + new FakeContentTag( + DOM.firstChild(lightDomEl), // content element + '', // selector + [el('')] // light DOM nodes of content tag + ) + ]), + null, lightDomEl); expect(toHtml(lightDom.expandedDomNodes())).toEqual([""]); @@ -184,7 +164,7 @@ export function main() { it("should work when the element injector array contains nulls", () => { var lightDomEl = el("
") - var lightDomView = new FakeView([null]); + var lightDomView = new FakeView(); var lightDom = new LightDom( lightDomView, @@ -197,14 +177,14 @@ export function main() { describe("redistribute", () => { it("should redistribute nodes between content tags with select property set", () => { - var contentA = new FakeContentTag("a"); - var contentB = new FakeContentTag("b"); + var contentA = new FakeContentTag(null, "a"); + var contentB = new FakeContentTag(null, "b"); var lightDomEl = el("") var lightDom = new LightDom(lightDomView, new FakeView([ - new FakeElementInjector(contentA, null), - new FakeElementInjector(contentB, null) + contentA, + contentB ]), lightDomEl); lightDom.redistribute(); @@ -214,14 +194,14 @@ export function main() { }); it("should support wildcard content tags", () => { - var wildcard = new FakeContentTag(null); - var contentB = new FakeContentTag("b"); + var wildcard = new FakeContentTag(null, ''); + var contentB = new FakeContentTag(null, "b"); var lightDomEl = el("") var lightDom = new LightDom(lightDomView, new FakeView([ - new FakeElementInjector(wildcard, null), - new FakeElementInjector(contentB, null) + wildcard, + contentB ]), lightDomEl); lightDom.redistribute(); diff --git a/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js b/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js index 532ddf7dda..8200adb28b 100644 --- a/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js +++ b/modules/angular2/test/core/compiler/shadow_dom/shadow_dom_emulation_integration_spec.js @@ -92,6 +92,18 @@ export function main() { }); } + it('should support simple components', inject([AsyncTestCompleter], (async) => { + var temp = '' + + '
A
' + + '
'; + + compile(temp, [Simple], (view, lc) => { + expect(view.nodes).toHaveText('SIMPLE(A)'); + + async.done(); + }); + })); + it('should support multiple content tags', inject([AsyncTestCompleter], (async) => { var temp = '' + '
B
' + @@ -367,6 +379,6 @@ class MyComp { function createView(pv) { var view = pv.instantiate(null, null); - view.hydrate(new Injector([]), null, {}); + view.hydrate(new Injector([]), null, null, {}); return view; } diff --git a/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js b/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js index d39837327c..e0ea87a7b5 100644 --- a/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js +++ b/modules/angular2/test/core/compiler/shadow_dom_strategy_spec.js @@ -56,10 +56,6 @@ export function main() { expect(shadowRoot).toHaveText('view'); }); - it('should should not transform template elements', () => { - expect(strategy.getTemplateCompileStep(null)).toBe(null); - }); - it('should rewrite style urls', () => { var step = strategy.getStyleCompileStep(null, 'http://base'); var styleElement = DOM.createStyleElement('.one {background-image: url("img.jpg");}'); diff --git a/modules/angular2/test/core/compiler/view_container_spec.js b/modules/angular2/test/core/compiler/view_container_spec.js index 0a4d5879fc..8ca2e18ef3 100644 --- a/modules/angular2/test/core/compiler/view_container_spec.js +++ b/modules/angular2/test/core/compiler/view_container_spec.js @@ -12,7 +12,7 @@ import {DynamicProtoChangeDetector, ChangeDetector, Lexer, Parser} from 'angular function createView(nodes) { var view = new View(null, nodes, MapWrapper.create()); var cd = new DynamicProtoChangeDetector(null).instantiate(view, []); - view.init(cd, [], [], [], [], [], [], []); + view.init(cd, [], [], [], [], [], [], [], [], []); return view; } @@ -48,7 +48,7 @@ class HydrateAwareFakeView { return this.isHydrated; } - hydrate(_, __, ___) { + hydrate(_, __, ___, ____) { this.isHydrated = true; } @@ -97,7 +97,7 @@ export function main() { } beforeEach(() => { - viewContainer.hydrate(new Injector([]), null); + viewContainer.hydrate(new Injector([]), null, null); var fillerView = createView([el('filler')]); viewContainer.insert(fillerView); }); @@ -213,11 +213,11 @@ export function main() { var fancyView; beforeEach(() => { var parser = new Parser(new Lexer()); - viewContainer.hydrate(new Injector([]), null); + viewContainer.hydrate(new Injector([]), null, null); var pv = new ProtoView(el('
{{}}
'), 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)); fancyView = pv.instantiate(null, null); }); diff --git a/modules/angular2/test/core/compiler/view_spec.js b/modules/angular2/test/core/compiler/view_spec.js index d84266ccbe..0d94a748cf 100644 --- a/modules/angular2/test/core/compiler/view_spec.js +++ b/modules/angular2/test/core/compiler/view_spec.js @@ -46,7 +46,7 @@ export function main() { function createView(protoView, eventManager: EventManager = null) { var ctx = new MyEvaluationContext(); var view = protoView.instantiate(null, eventManager); - view.hydrate(null, null, ctx); + view.hydrate(null, null, null, ctx); return view; } @@ -69,7 +69,7 @@ export function main() { it('should be able to be hydrated and dehydrated', () => { var ctx = new Object(); - view.hydrate(null, null, ctx); + view.hydrate(null, null, null, ctx); expect(view.hydrated()).toBe(true); view.dehydrate(); @@ -78,7 +78,7 @@ export function main() { it('should hydrate and dehydrate the change detector', () => { var ctx = new Object(); - view.hydrate(null, null, ctx); + view.hydrate(null, null, null, ctx); expect(view.changeDetector.hydrated()).toBe(true); view.dehydrate(); @@ -114,7 +114,7 @@ export function main() { it('when dehydrated should set locals to null', () => { view.setLocal('context-foo', 'bar'); view.dehydrate(); - view.hydrate(null, null, new Object()); + view.hydrate(null, null, null, new Object()); expect(view.context.get('template-foo')).toBe(null); }); @@ -136,7 +136,7 @@ export function main() { var pv = new ProtoView(templateAwareCreateElement('
'), new DynamicProtoChangeDetector(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(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', () => { var pv = new ProtoView(templateAwareCreateElement('
'), new DynamicProtoChangeDetector(null), null); - pv.bindElement(null); + pv.bindElement(null, 0, null); pv.bindElementProperty(parser.parseBinding('a', null), 'prop', reflector.setter('prop')); 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[0]).toBe(view.nodes[0]); }); @@ -158,11 +158,11 @@ export function main() { it('should collect property bindings on child elements with ng-binding class', () => { var pv = new ProtoView(templateAwareCreateElement('
'), new DynamicProtoChangeDetector(null), null); - pv.bindElement(null); + pv.bindElement(null, 0, null); pv.bindElementProperty(parser.parseBinding('b', null), 'a', reflector.setter('a')); 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[0]).toBe(view.nodes[0].childNodes[1]); }); @@ -174,12 +174,12 @@ export function main() { it('should collect text nodes under the root element', () => { var pv = new ProtoView(templateAwareCreateElement('
{{}}{{}}
'), new DynamicProtoChangeDetector(null), null); - pv.bindElement(null); + pv.bindElement(null, 0, null); pv.bindTextNode(0, parser.parseBinding('a', null)); pv.bindTextNode(2, parser.parseBinding('b', 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[0]).toBe(view.nodes[0].childNodes[0]); 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', () => { var pv = new ProtoView(templateAwareCreateElement('
{{}}
'), new DynamicProtoChangeDetector(null), null); - pv.bindElement(null); + pv.bindElement(null, 0, null); pv.bindTextNode(0, parser.parseBinding('b', 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[0]).toBe(view.nodes[0].childNodes[1].childNodes[0]); }); @@ -207,7 +207,7 @@ export function main() { new NativeShadowDomStrategy(null)); pv.instantiateInPlace = true; var view = pv.instantiate(null, null); - view.hydrate(null, null, null); + view.hydrate(null, null, null, null); expect(view.nodes[0]).toBe(template); }); @@ -216,7 +216,7 @@ export function main() { var pv = new ProtoView(template, new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(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); }); }); @@ -233,10 +233,10 @@ export function main() { it('should use the directives of the ProtoElementInjector', () => { var pv = new ProtoView(el('
'), 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); - view.hydrate(null, null, null); + view.hydrate(null, null, null, null); expect(view.elementInjectors.length).toBe(1); expect(view.elementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); }); @@ -245,11 +245,11 @@ export function main() { var pv = new ProtoView(el('
'), new DynamicProtoChangeDetector(null), null); var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]); - pv.bindElement(protoParent); - pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective])); + pv.bindElement(null, 0, protoParent); + pv.bindElement(null, 0, new ProtoElementInjector(protoParent, 1, [AnotherDirective])); 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[0].get(SomeDirective) instanceof SomeDirective).toBe(true); expect(view.elementInjectors[1].parent).toBe(view.elementInjectors[0]); @@ -259,9 +259,9 @@ export function main() { var pv = new ProtoView(el('
'), new DynamicProtoChangeDetector(null), null); var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]); - pv.bindElement(protoParent); + pv.bindElement(null, 0, protoParent); var testProtoElementInjector = new TestProtoElementInjector(protoParent, 1, [AnotherDirective]); - pv.bindElement(testProtoElementInjector); + pv.bindElement(null, 0, testProtoElementInjector); var hostProtoInjector = new ProtoElementInjector(null, 0, []); 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', () => { var pv = new ProtoView(el('
'), 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]); - pv.bindElement(testProtoElementInjector); + pv.bindElement(null, 0, testProtoElementInjector); var hostProtoInjector = new ProtoElementInjector(null, 0, []); var hostInjector = hostProtoInjector.instantiate(null, null); @@ -292,11 +292,11 @@ export function main() { var pv = new ProtoView(el('
'), new DynamicProtoChangeDetector(null), null); var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]); - pv.bindElement(protoParent); - pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective])); + pv.bindElement(null, 0, protoParent); + pv.bindElement(null, 0, new ProtoElementInjector(protoParent, 1, [AnotherDirective])); 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[0].get(SomeDirective) instanceof SomeDirective).toBe(true); }); @@ -304,11 +304,11 @@ export function main() { it('should collect multiple root element injectors', () => { var pv = new ProtoView(el('
'), new DynamicProtoChangeDetector(null), null); - pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective])); - pv.bindElement(new ProtoElementInjector(null, 2, [AnotherDirective])); + pv.bindElement(null, 0, new ProtoElementInjector(null, 1, [SomeDirective])); + pv.bindElement(null, 0, new ProtoElementInjector(null, 2, [AnotherDirective])); 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[0].get(SomeDirective) instanceof SomeDirective).toBe(true); expect(view.rootElementInjectors[1].get(AnotherDirective) instanceof AnotherDirective).toBe(true); @@ -322,7 +322,7 @@ export function main() { function createComponentWithSubPV(subProtoView) { var pv = new ProtoView(el(''), 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.nestedProtoView = subProtoView; return pv; @@ -331,7 +331,7 @@ export function main() { function createNestedView(protoView) { ctx = new MyEvaluationContext(); var view = protoView.instantiate(null, null); - view.hydrate(new Injector([]), null, ctx); + view.hydrate(new Injector([]), null, null, ctx); return view; } @@ -351,7 +351,7 @@ export function main() { el('
hello shadow dom
'), new DynamicProtoChangeDetector(null), null); - subpv.bindElement( + subpv.bindElement(null, 0, new ProtoElementInjector(null, 0, [ServiceDependentDecorator])); var pv = createComponentWithSubPV(subpv); @@ -376,7 +376,7 @@ export function main() { el('
hello shadow dom
'), new DynamicProtoChangeDetector(null), null); - subpv.bindElement( + subpv.bindElement(null, 0, new ProtoElementInjector(null, 0, [ServiceDependentDecorator])); var pv = createComponentWithSubPV(subpv); @@ -406,7 +406,7 @@ export function main() { var pv = new ProtoView(el(''), 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.nestedProtoView = subpv; @@ -422,7 +422,7 @@ export function main() { el('
'), new DynamicProtoChangeDetector(null), null); var pv = new ProtoView(el(''), 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.nestedProtoView = templateProtoView; @@ -468,7 +468,7 @@ export function main() { function createProtoView() { var pv = new ProtoView(el('
'), 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)); return pv; } @@ -503,7 +503,7 @@ export function main() { it('should support custom event emitters', () => { var pv = new ProtoView(el('
'), 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)); createViewAndContext(pv); @@ -524,7 +524,7 @@ export function main() { it('should bind to directive events', () => { var pv = new ProtoView(el('
'), 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); view = createView(pv, new EventManager([new DomEventsPlugin()], new FakeVmTurnZone())); @@ -549,7 +549,7 @@ export function main() { it('should consume text node changes', () => { var pv = new ProtoView(el('
{{}}
'), new DynamicProtoChangeDetector(null), null); - pv.bindElement(null); + pv.bindElement(null, 0, null); pv.bindTextNode(0, parser.parseBinding('foo', null)); createViewAndChangeDetector(pv); @@ -561,7 +561,7 @@ export function main() { it('should consume element binding changes', () => { var pv = new ProtoView(el('
'), new DynamicProtoChangeDetector(null), null); - pv.bindElement(null); + pv.bindElement(null, 0, null); pv.bindElementProperty(parser.parseBinding('foo', null), 'id', reflector.setter('id')); createViewAndChangeDetector(pv); @@ -573,7 +573,7 @@ export function main() { it('should consume directive watch expression change', () => { var pv = new ProtoView(el('
'), 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')); createViewAndChangeDetector(pv); @@ -586,7 +586,7 @@ export function main() { var pv = new ProtoView(el('
'), 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]})) ])); pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a')); @@ -605,7 +605,7 @@ export function main() { var pv = new ProtoView(el('
'), 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]})) ])); pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a')); @@ -643,7 +643,7 @@ export function main() { someComponentDirective, new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(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); }); @@ -652,7 +652,7 @@ export function main() { someComponentDirective, new DynamicProtoChangeDetector(null), new NativeShadowDomStrategy(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'); }); }); diff --git a/modules/angular2/test/directives/foreach_spec.js b/modules/angular2/test/directives/foreach_spec.js index da8a47adce..61cf60693a 100644 --- a/modules/angular2/test/directives/foreach_spec.js +++ b/modules/angular2/test/directives/foreach_spec.js @@ -45,7 +45,7 @@ export function main() { function createView(pv) { component = new TestComponent(); view = pv.instantiate(null, null); - view.hydrate(new Injector([]), null, component); + view.hydrate(new Injector([]), null, null, component); cd = view.changeDetector; } diff --git a/modules/angular2/test/directives/if_spec.js b/modules/angular2/test/directives/if_spec.js index ffc143c621..79fd1d9193 100644 --- a/modules/angular2/test/directives/if_spec.js +++ b/modules/angular2/test/directives/if_spec.js @@ -57,7 +57,7 @@ export function main() { function createView(pv) { component = new TestComponent(); view = pv.instantiate(null, null); - view.hydrate(new Injector([]), null, component); + view.hydrate(new Injector([]), null, null, component); cd = view.changeDetector; } diff --git a/modules/angular2/test/directives/non_bindable_spec.js b/modules/angular2/test/directives/non_bindable_spec.js index 52b057ec82..49bf9038e0 100644 --- a/modules/angular2/test/directives/non_bindable_spec.js +++ b/modules/angular2/test/directives/non_bindable_spec.js @@ -54,7 +54,7 @@ export function main() { function createView(pv) { component = new TestComponent(); view = pv.instantiate(null, null); - view.hydrate(new Injector([]), null, component); + view.hydrate(new Injector([]), null, null, component); cd = view.changeDetector; } diff --git a/modules/angular2/test/directives/switch_spec.js b/modules/angular2/test/directives/switch_spec.js index 9907856edc..f1d84844eb 100644 --- a/modules/angular2/test/directives/switch_spec.js +++ b/modules/angular2/test/directives/switch_spec.js @@ -51,7 +51,7 @@ export function main() { function createView(pv) { component = new TestComponent(); view = pv.instantiate(null, null); - view.hydrate(new Injector([]), null, component); + view.hydrate(new Injector([]), null, null, component); cd = view.changeDetector; } diff --git a/modules/angular2/test/forms/integration_spec.js b/modules/angular2/test/forms/integration_spec.js index 5a535a45f3..41da4e43a5 100644 --- a/modules/angular2/test/forms/integration_spec.js +++ b/modules/angular2/test/forms/integration_spec.js @@ -63,7 +63,7 @@ export function main() { compiler.compile(componentType).then((pv) => { var view = pv.instantiate(null, null); - view.hydrate(new Injector([]), null, context); + view.hydrate(new Injector([]), null, null, context); detectChanges(view); callback(view); });