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:
parent
115ac5f290
commit
70c875ee14
|
@ -67,7 +67,7 @@ function _injectorBindings(appComponentType): List<Binding> {
|
|||
// 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,
|
||||
|
|
|
@ -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<Type, Promise>;
|
||||
_shadowDomStrategy: ShadowDomStrategy;
|
||||
_shadowDomDirectives: List<DirectiveMetadata>;
|
||||
_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<CompileStep> {
|
||||
// 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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. '<div [class]="foo">' : 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 !== '') {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Content>):List<Content> {
|
||||
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<vcs.length; i++) {
|
||||
var vc = vcs[i];
|
||||
var contentTag = contentTags[i];
|
||||
if (isPresent(contentTag)) {
|
||||
ListWrapper.push(acc, contentTag);
|
||||
}
|
||||
if (isPresent(vc)) {
|
||||
ListWrapper.forEach(vc.contentTagContainers(), (view) => {
|
||||
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<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;
|
||||
}
|
||||
|
@ -119,10 +127,10 @@ function redistributeNodes(contents:List<Content>, nodes:List) {
|
|||
var select = content.select;
|
||||
var matchSelector = (n) => DOM.elementMatches(n, select);
|
||||
|
||||
if (isBlank(select)) {
|
||||
// Empty selector is identical to <content/>
|
||||
if (select.length === 0) {
|
||||
content.insert(nodes);
|
||||
ListWrapper.clear(nodes);
|
||||
|
||||
} else {
|
||||
var matchingNodes = ListWrapper.filter(nodes, matchSelector);
|
||||
content.insert(matchingNodes);
|
||||
|
|
|
@ -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<Type> { 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<Type> {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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<View>;
|
||||
viewContainers: List<ViewContainer>;
|
||||
contentTags: List<Content>;
|
||||
preBuiltObjects: List<PreBuiltObjects>;
|
||||
lightDoms: List<LightDom>;
|
||||
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<LightDom>) {
|
||||
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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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('<div></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);
|
||||
inj.get(NeedsPropertySetter).setProp('foobar');
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = `<script type="ng/content"></script>`;
|
||||
var _scriptStart = `<script start=""></script>`;
|
||||
var _scriptEnd = `<script end=""></script>`;
|
||||
|
||||
export function main() {
|
||||
describe('Content', function() {
|
||||
it("should insert the nodes", () => {
|
||||
var parent = el("<div><content></content></div>");
|
||||
var content = DOM.firstChild(parent);
|
||||
var parent;
|
||||
var content;
|
||||
|
||||
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>")])
|
||||
|
||||
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", () => {
|
||||
var parent = el("<div><content></content></div>");
|
||||
var content = DOM.firstChild(parent);
|
||||
|
||||
var c = new Content(null, new NgElement(content));
|
||||
var c = new Content(null, content, '');
|
||||
c.insert([el("<a></a>")]);
|
||||
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", () => {
|
||||
var parent = el("<div><content></content></div>");
|
||||
var content = DOM.firstChild(parent);
|
||||
|
||||
var c = new Content(null, new NgElement(content));
|
||||
var c = new Content(null, content, '');
|
||||
c.insert([el("<a></a>")]);
|
||||
c.insert([]);
|
||||
|
||||
expect(DOM.getInnerHTML(parent)).toEqual(`${_script}${_script}`);
|
||||
expect(DOM.getInnerHTML(parent)).toEqual(`${_scriptStart}${_scriptEnd}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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('<script></script>'));
|
||||
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]);
|
||||
});
|
||||
|
||||
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('<script></script>'));
|
||||
var vc = new FakeViewContainer(null, null, [
|
||||
new FakeView([tag])
|
||||
]);
|
||||
|
||||
var shadowDomView = new FakeView([new FakeElementInjector(null, vp)]);
|
||||
|
||||
var lightDom = new LightDom(lightDomView, shadowDomView, el("<div></div>"));
|
||||
var shadowDomView = new FakeView([vc]);
|
||||
var lightDom = new LightDom(lightDomView, shadowDomView,
|
||||
el("<div></div>"));
|
||||
|
||||
expect(lightDom.contentTags()).toEqual([tag]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("expanded roots", () => {
|
||||
describe("expandedDomNodes", () => {
|
||||
it("should contain root nodes", () => {
|
||||
var lightDomEl = el("<div><a></a></div>")
|
||||
var lightDom = new LightDom(lightDomView, new FakeView(), lightDomEl);
|
||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||
});
|
||||
|
||||
it("should include ViewContainer nodes", () => {
|
||||
var lightDomEl = el("<div><template></template></div>")
|
||||
|
||||
var lightDomView = new FakeView([
|
||||
new FakeElementInjector(
|
||||
null,
|
||||
new FakeViewContainer([el("<a></a>")]),
|
||||
DOM.firstChild(lightDomEl))]);
|
||||
|
||||
it("should include view container nodes", () => {
|
||||
var lightDomEl = el("<div><template></template></div>");
|
||||
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);
|
||||
|
||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||
});
|
||||
|
||||
it("should include content nodes", () => {
|
||||
var lightDomEl = el("<div><content></content></div>")
|
||||
|
||||
var lightDomView = new FakeView([
|
||||
new FakeElementInjector(
|
||||
new FakeContentTag(null, [el("<a></a>")]),
|
||||
null,
|
||||
DOM.firstChild(lightDomEl))]);
|
||||
|
||||
var lightDomEl = el("<div><content></content></div>");
|
||||
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);
|
||||
|
||||
expect(toHtml(lightDom.expandedDomNodes())).toEqual(["<a></a>"]);
|
||||
|
@ -184,7 +164,7 @@ export function main() {
|
|||
it("should work when the element injector array contains nulls", () => {
|
||||
var lightDomEl = el("<div><a></a></div>")
|
||||
|
||||
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("<div><a>1</a><b>2</b><a>3</a></div>")
|
||||
|
||||
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("<div><a>1</a><b>2</b><a>3</a></div>")
|
||||
|
||||
var lightDom = new LightDom(lightDomView, new FakeView([
|
||||
new FakeElementInjector(wildcard, null),
|
||||
new FakeElementInjector(contentB, null)
|
||||
wildcard,
|
||||
contentB
|
||||
]), lightDomEl);
|
||||
|
||||
lightDom.redistribute();
|
||||
|
|
|
@ -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) => {
|
||||
var temp = '<multiple-content-tags>' +
|
||||
'<div>B</div>' +
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");}');
|
||||
|
|
|
@ -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>filler</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('<div class="ng-binding">{{}}</div>'),
|
||||
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);
|
||||
});
|
||||
|
|
|
@ -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('<div id="1"></div>'),
|
||||
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('<div [prop]="a" class="ng-binding"></div>'),
|
||||
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('<div><span></span><span class="ng-binding"></span></div>'),
|
||||
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('<div class="ng-binding">{{}}<span></span>{{}}</div>'),
|
||||
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('<div><span> </span><span class="ng-binding">{{}}</span></div>'),
|
||||
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('<div class="ng-binding"></div>'),
|
||||
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('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||
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('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||
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('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||
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('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||
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('<div><span class="ng-binding"></span><span class="ng-binding"></span></div>'),
|
||||
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('<cmp class="ng-binding"></cmp>'),
|
||||
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('<div dec class="ng-binding">hello shadow dom</div>'),
|
||||
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('<div dec class="ng-binding">hello shadow dom</div>'),
|
||||
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('<cmp class="ng-binding"></cmp>'),
|
||||
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('<div id="1"></div>'), new DynamicProtoChangeDetector(null), null);
|
||||
var pv = new ProtoView(el('<someTmpl class="ng-binding"></someTmpl>'),
|
||||
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('<div class="ng-binding"><div></div></div>'),
|
||||
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('<div class="ng-binding"><div></div></div>'),
|
||||
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('<div class="ng-binding"></div>'),
|
||||
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('<div class="ng-binding">{{}}</div>'),
|
||||
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('<div class="ng-binding"></div>'),
|
||||
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('<div class="ng-binding"></div>'),
|
||||
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('<div class="ng-binding"></div>'),
|
||||
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('<div class="ng-binding"></div>'),
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue