Skip to content

Commit 70c875e

Browse files
committed
refactor(shadow dom): do not use injectors nor directives
This prepares us for the app/render split in the compiler.
1 parent 115ac5f commit 70c875e

31 files changed

+368
-344
lines changed

modules/angular2/src/core/application.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function _injectorBindings(appComponentType): List<Binding> {
6767
// the angular application. Thus the context and lightDomInjector are
6868
// empty.
6969
var view = appProtoView.instantiate(null, eventManager);
70-
view.hydrate(injector, null, new Object());
70+
view.hydrate(injector, null, null, new Object());
7171
return view;
7272
});
7373
}, [ChangeDetection, Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken,

modules/angular2/src/core/compiler/compiler.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {CompileElement} from './pipeline/compile_element';
1111
import {createDefaultSteps} from './pipeline/default_steps';
1212
import {TemplateLoader} from './template_loader';
1313
import {TemplateResolver} from './template_resolver';
14-
import {DirectiveMetadata} from './directive_metadata';
1514
import {Template} from '../annotations/template';
1615
import {ShadowDomStrategy} from './shadow_dom_strategy';
1716
import {CompileStep} from './pipeline/compile_step';
@@ -56,7 +55,6 @@ export class Compiler {
5655
_templateLoader:TemplateLoader;
5756
_compiling:Map<Type, Promise>;
5857
_shadowDomStrategy: ShadowDomStrategy;
59-
_shadowDomDirectives: List<DirectiveMetadata>;
6058
_templateResolver: TemplateResolver;
6159
_componentUrlMapper: ComponentUrlMapper;
6260
_urlResolver: UrlResolver;
@@ -80,11 +78,6 @@ export class Compiler {
8078
this._templateLoader = templateLoader;
8179
this._compiling = MapWrapper.create();
8280
this._shadowDomStrategy = shadowDomStrategy;
83-
this._shadowDomDirectives = [];
84-
var types = shadowDomStrategy.polyfillDirectives();
85-
for (var i = 0; i < types.length; i++) {
86-
ListWrapper.push(this._shadowDomDirectives, reader.read(types[i]));
87-
}
8881
this._templateResolver = templateResolver;
8982
this._componentUrlMapper = componentUrlMapper;
9083
this._urlResolver = urlResolver;
@@ -93,12 +86,8 @@ export class Compiler {
9386
}
9487

9588
createSteps(component:Type, template: Template):List<CompileStep> {
96-
// Merge directive metadata (from the template and from the shadow dom strategy)
97-
var dirMetadata = [];
98-
var tplMetadata = ListWrapper.map(this._flattenDirectives(template),
89+
var dirMetadata = ListWrapper.map(this._flattenDirectives(template),
9990
(d) => this._reader.read(d));
100-
dirMetadata = ListWrapper.concat(dirMetadata, tplMetadata);
101-
dirMetadata = ListWrapper.concat(dirMetadata, this._shadowDomDirectives);
10291

10392
var cmpMetadata = this._reader.read(component);
10493

modules/angular2/src/core/compiler/element_binder.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {int, isBlank, BaseException} from 'angular2/src/facade/lang';
12
import {ProtoElementInjector} from './element_injector';
23
import {DirectiveMetadata} from './directive_metadata';
34
import {List, StringMap} from 'angular2/src/facade/collection';
@@ -11,12 +12,24 @@ export class ElementBinder {
1112
hasElementPropertyBindings:boolean;
1213
nestedProtoView: ProtoView;
1314
events:StringMap;
15+
contentTagSelector:string;
16+
parent:ElementBinder;
17+
index:int;
18+
distanceToParent:int;
1419
constructor(
20+
index:int, parent:ElementBinder, distanceToParent: int,
1521
protoElementInjector: ProtoElementInjector, componentDirective:DirectiveMetadata,
1622
viewportDirective:DirectiveMetadata) {
23+
if (isBlank(index)) {
24+
throw new BaseException('null index not allowed.');
25+
}
26+
1727
this.protoElementInjector = protoElementInjector;
1828
this.componentDirective = componentDirective;
1929
this.viewportDirective = viewportDirective;
30+
this.parent = parent;
31+
this.index = index;
32+
this.distanceToParent = distanceToParent;
2033
// updated later when events are bound
2134
this.events = null;
2235
// updated later when text nodes are bound
@@ -25,5 +38,7 @@ export class ElementBinder {
2538
this.hasElementPropertyBindings = false;
2639
// updated later, so we are able to resolve cycles
2740
this.nestedProtoView = null;
41+
// updated later in the compilation pipeline
42+
this.contentTagSelector = null;
2843
}
2944
}

modules/angular2/src/core/compiler/element_injector.js

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {Injector, Key, Dependency, bind, Binding, NoProviderError, ProviderError
55
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
66
import {EventEmitter, PropertySetter} from 'angular2/src/core/annotations/di';
77
import * as viewModule from 'angular2/src/core/compiler/view';
8-
import {LightDom, DestinationLightDom} from 'angular2/src/core/compiler/shadow_dom_emulation/light_dom';
98
import {ViewContainer} from 'angular2/src/core/compiler/view_container';
109
import {NgElement} from 'angular2/src/core/dom/element';
1110
import {Directive, onChange, onDestroy} from 'angular2/src/core/annotations/annotations'
@@ -24,17 +23,13 @@ class StaticKeys {
2423
viewId:number;
2524
ngElementId:number;
2625
viewContainerId:number;
27-
destinationLightDomId:number;
28-
lightDomId:number;
2926
bindingPropagationConfigId:number;
3027

3128
constructor() {
3229
//TODO: vsavkin Key.annotate(Key.get(View), 'static')
3330
this.viewId = Key.get(viewModule.View).id;
3431
this.ngElementId = Key.get(NgElement).id;
3532
this.viewContainerId = Key.get(ViewContainer).id;
36-
this.destinationLightDomId = Key.get(DestinationLightDom).id;
37-
this.lightDomId = Key.get(LightDom).id;
3833
this.bindingPropagationConfigId = Key.get(BindingPropagationConfig).id;
3934
}
4035

@@ -166,14 +161,12 @@ export class PreBuiltObjects {
166161
view:viewModule.View;
167162
element:NgElement;
168163
viewContainer:ViewContainer;
169-
lightDom:LightDom;
170164
bindingPropagationConfig:BindingPropagationConfig;
171-
constructor(view, element:NgElement, viewContainer:ViewContainer, lightDom:LightDom,
165+
constructor(view, element:NgElement, viewContainer:ViewContainer,
172166
bindingPropagationConfig:BindingPropagationConfig) {
173167
this.view = view;
174168
this.element = element;
175169
this.viewContainer = viewContainer;
176-
this.lightDom = lightDom;
177170
this.bindingPropagationConfig = bindingPropagationConfig;
178171
}
179172
}
@@ -577,13 +570,6 @@ export class ElementInjector extends TreeNode {
577570
if (keyId === staticKeys.ngElementId) return this._preBuiltObjects.element;
578571
if (keyId === staticKeys.viewContainerId) return this._preBuiltObjects.viewContainer;
579572
if (keyId === staticKeys.bindingPropagationConfigId) return this._preBuiltObjects.bindingPropagationConfig;
580-
if (keyId === staticKeys.destinationLightDomId) {
581-
var p:ElementInjector = this.directParent();
582-
return isPresent(p) ? p._preBuiltObjects.lightDom : null;
583-
}
584-
if (keyId === staticKeys.lightDomId) {
585-
return this._preBuiltObjects.lightDom;
586-
}
587573

588574
//TODO add other objects as needed
589575
return _undefined;

modules/angular2/src/core/compiler/pipeline/compile_element.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ export class CompileElement {
3636
inheritedProtoView:ProtoView;
3737
inheritedProtoElementInjector:ProtoElementInjector;
3838
inheritedElementBinder:ElementBinder;
39-
distanceToParentInjector:number;
39+
distanceToParentInjector:int;
40+
distanceToParentBinder:int;
4041
compileChildren: boolean;
4142
ignoreBindings: boolean;
4243
elementDescription: string; // e.g. '<div [class]="foo">' : used to provide context in case of error
44+
contentTagSelector: string;
4345

4446
constructor(element, compilationUnit = '') {
4547
this.element = element;
@@ -65,9 +67,11 @@ export class CompileElement {
6567
// an own elementBinder
6668
this.inheritedElementBinder = null;
6769
this.distanceToParentInjector = 0;
70+
this.distanceToParentBinder = 0;
6871
this.compileChildren = true;
6972
// set to true to ignore all the bindings on the element
7073
this.ignoreBindings = false;
74+
this.contentTagSelector = null;
7175
// description is calculated here as compilation steps may change the element
7276
var tplDesc = assertionsEnabled()? getElementDescription(element) : null;
7377
if (compilationUnit !== '') {

modules/angular2/src/core/compiler/pipeline/default_steps.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {ChangeDetection, Parser} from 'angular2/change_detection';
22
import {List, ListWrapper} from 'angular2/src/facade/collection';
3-
import {isPresent} from 'angular2/src/facade/lang';
43

54
import {PropertyBindingParser} from './property_binding_parser';
65
import {TextInterpolationParser} from './text_interpolation_parser';
@@ -32,6 +31,7 @@ export function createDefaultSteps(
3231
var steps = [
3332
new ViewSplitter(parser),
3433
cssProcessor.getCompileStep(compiledComponent, shadowDomStrategy, templateUrl),
34+
shadowDomStrategy.getTemplateCompileStep(compiledComponent),
3535
new PropertyBindingParser(parser),
3636
new DirectiveParser(directives),
3737
new TextInterpolationParser(parser),
@@ -41,10 +41,5 @@ export function createDefaultSteps(
4141
new ElementBinderBuilder(parser),
4242
];
4343

44-
var shadowDomStep = shadowDomStrategy.getTemplateCompileStep(compiledComponent);
45-
if (isPresent(shadowDomStep)) {
46-
ListWrapper.push(steps, shadowDomStep);
47-
}
48-
4944
return steps;
5045
}

modules/angular2/src/core/compiler/pipeline/directive_parser.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ export class DirectiveParser extends CompileStep {
4949
var classList = current.classList();
5050

5151
var cssSelector = new CssSelector();
52-
cssSelector.setElement(DOM.nodeName(current.element));
52+
var nodeName = DOM.nodeName(current.element);
53+
cssSelector.setElement(nodeName);
5354
for (var i=0; i < classList.length; i++) {
5455
cssSelector.addClassName(classList[i]);
5556
}

modules/angular2/src/core/compiler/pipeline/element_binder_builder.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ export class ElementBinderBuilder extends CompileStep {
135135

136136
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
137137
var elementBinder = null;
138+
var parentElementBinder = null;
139+
var distanceToParentBinder = this._getDistanceToParentBinder(parent, current);
140+
if (isPresent(parent)) {
141+
parentElementBinder = parent.inheritedElementBinder;
142+
}
138143
if (current.hasBindings) {
139144
var protoView = current.inheritedProtoView;
140145
var protoInjectorWasBuilt = isBlank(parent) ? true :
@@ -143,8 +148,9 @@ export class ElementBinderBuilder extends CompileStep {
143148
var currentProtoElementInjector = protoInjectorWasBuilt ?
144149
current.inheritedProtoElementInjector : null;
145150

146-
elementBinder = protoView.bindElement(currentProtoElementInjector,
147-
current.componentDirective, current.viewportDirective);
151+
elementBinder = protoView.bindElement(parentElementBinder, distanceToParentBinder,
152+
currentProtoElementInjector, current.componentDirective, current.viewportDirective);
153+
current.distanceToParentBinder = 0;
148154

149155
if (isPresent(current.textNodeBindings)) {
150156
this._bindTextNodes(protoView, current);
@@ -155,15 +161,23 @@ export class ElementBinderBuilder extends CompileStep {
155161
if (isPresent(current.eventBindings)) {
156162
this._bindEvents(protoView, current);
157163
}
164+
if (isPresent(current.contentTagSelector)) {
165+
elementBinder.contentTagSelector = current.contentTagSelector;
166+
}
158167
var directives = current.getAllDirectives();
159168
this._bindDirectiveProperties(directives, current);
160169
this._bindDirectiveEvents(directives, current);
161170
} else if (isPresent(parent)) {
162-
elementBinder = parent.inheritedElementBinder;
171+
elementBinder = parentElementBinder;
172+
current.distanceToParentBinder = distanceToParentBinder;
163173
}
164174
current.inheritedElementBinder = elementBinder;
165175
}
166176

177+
_getDistanceToParentBinder(parent, current) {
178+
return isPresent(parent) ? parent.distanceToParentBinder + 1 : 0;
179+
}
180+
167181
_bindTextNodes(protoView, compileElement) {
168182
MapWrapper.forEach(compileElement.textNodeBindings, (expression, indexInParent) => {
169183
protoView.bindTextNode(indexInParent, expression);

modules/angular2/src/core/compiler/pipeline/element_binding_marker.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ export class ElementBindingMarker extends CompileStep {
3737
(isPresent(current.eventBindings) && MapWrapper.size(current.eventBindings)>0) ||
3838
(isPresent(current.decoratorDirectives) && current.decoratorDirectives.length > 0) ||
3939
isPresent(current.viewportDirective) ||
40-
isPresent(current.componentDirective);
40+
isPresent(current.componentDirective) ||
41+
isPresent(current.contentTagSelector);
4142

4243
if (hasBindings) {
4344
var element = current.element;

modules/angular2/src/core/compiler/shadow_dom_emulation/content_tag.js

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
import {Decorator} from '../../annotations/annotations';
21
import * as ldModule from './light_dom';
3-
import {Inject} from 'angular2/di';
42
import {DOM} from 'angular2/src/dom/dom_adapter';
53
import {isPresent} from 'angular2/src/facade/lang';
64
import {List, ListWrapper} from 'angular2/src/facade/collection';
7-
import {NgElement} from 'angular2/src/core/dom/element';
85

96
class ContentStrategy {
107
nodes:List;
@@ -17,23 +14,16 @@ class ContentStrategy {
1714
* and thus does not affect redistribution.
1815
*/
1916
class RenderedContent extends ContentStrategy {
20-
static _lazyScriptTemplate;
2117
beginScript;
2218
endScript;
2319

2420
constructor(contentEl) {
2521
super();
26-
this._replaceContentElementWithScriptTags(contentEl);
22+
this.beginScript = contentEl;
23+
this.endScript = DOM.nextSibling(this.beginScript);
2724
this.nodes = [];
2825
}
2926

30-
_scriptTemplate() {
31-
if (!isPresent(RenderedContent._lazyScriptTemplate)) {
32-
RenderedContent._lazyScriptTemplate = DOM.createScriptTag('type', 'ng/content');
33-
}
34-
return RenderedContent._lazyScriptTemplate;
35-
}
36-
3727
// Inserts the nodes in between the start and end scripts.
3828
// Previous content is removed.
3929
insert(nodes:List) {
@@ -42,16 +32,6 @@ class RenderedContent extends ContentStrategy {
4232
this._removeNodesUntil(ListWrapper.isEmpty(nodes) ? this.endScript : nodes[0]);
4333
}
4434

45-
// Replaces the content tag with a pair of script tags
46-
_replaceContentElementWithScriptTags(contentEl) {
47-
this.beginScript = DOM.clone(this._scriptTemplate());
48-
this.endScript = DOM.clone(this._scriptTemplate());
49-
50-
DOM.insertBefore(contentEl, this.beginScript);
51-
DOM.insertBefore(contentEl, this.endScript);
52-
DOM.removeChild(DOM.parentElement(contentEl), contentEl);
53-
}
54-
5535
_removeNodesUntil(node) {
5636
var p = DOM.parentElement(this.beginScript);
5737
for (var next = DOM.nextSibling(this.beginScript);
@@ -83,18 +63,17 @@ class IntermediateContent extends ContentStrategy {
8363
}
8464

8565

86-
@Decorator({
87-
selector: 'content'
88-
})
8966
export class Content {
9067
select:string;
9168
_strategy:ContentStrategy;
69+
contentStartElement;
9270

93-
constructor(@Inject(ldModule.DestinationLightDom) destinationLightDom, contentEl:NgElement) {
94-
this.select = contentEl.getAttribute('select');
71+
constructor(destinationLightDom:ldModule.LightDom, contentStartEl, selector:string) {
72+
this.select = selector;
73+
this.contentStartElement = contentStartEl;
9574
this._strategy = isPresent(destinationLightDom) ?
9675
new IntermediateContent(destinationLightDom) :
97-
new RenderedContent(contentEl.domElement);
76+
new RenderedContent(contentStartEl);
9877
}
9978

10079
nodes():List {

0 commit comments

Comments
 (0)