Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit 8016340

Browse files
committed
feat(compiler): Initial TagggingCompiler implementation
1 parent 96d46c5 commit 8016340

File tree

8 files changed

+346
-103
lines changed

8 files changed

+346
-103
lines changed

lib/core_dom/compiler.dart

Lines changed: 1 addition & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,5 @@
11
part of angular.core.dom;
22

33
abstract class Compiler implements Function {
4-
WalkingViewFactory call(List<dom.Node> elements, DirectiveMap directives);
5-
}
6-
7-
@NgInjectableService()
8-
class WalkingCompiler implements Compiler {
9-
final Profiler _perf;
10-
final Expando _expando;
11-
12-
WalkingCompiler(this._perf, this._expando);
13-
14-
List<ElementBinderTreeRef> _compileView(NodeCursor domCursor, NodeCursor templateCursor,
15-
ElementBinder existingElementBinder,
16-
DirectiveMap directives) {
17-
if (domCursor.current == null) return null;
18-
19-
List<ElementBinderTreeRef> elementBinders = null; // don't pre-create to create sparse tree and prevent GC pressure.
20-
21-
do {
22-
var subtrees, binder;
23-
24-
ElementBinder elementBinder = existingElementBinder == null
25-
? directives.selector(domCursor.current)
26-
: existingElementBinder;
27-
28-
if (elementBinder.hasTemplate) {
29-
elementBinder.templateViewFactory = _compileTransclusion(
30-
domCursor, templateCursor,
31-
elementBinder.template, elementBinder.templateBinder, directives);
32-
}
33-
34-
if (elementBinder.shouldCompileChildren) {
35-
if (domCursor.descend()) {
36-
templateCursor.descend();
37-
38-
subtrees =
39-
_compileView(domCursor, templateCursor, null, directives);
40-
41-
domCursor.ascend();
42-
templateCursor.ascend();
43-
}
44-
}
45-
46-
if (elementBinder.hasDirectives) {
47-
binder = elementBinder;
48-
}
49-
50-
if (elementBinders == null) elementBinders = [];
51-
elementBinders.add(new ElementBinderTreeRef(templateCursor.index, new ElementBinderTree(binder, subtrees)));
52-
} while (templateCursor.moveNext() && domCursor.moveNext());
53-
54-
return elementBinders;
55-
}
56-
57-
WalkingViewFactory _compileTransclusion(
58-
NodeCursor domCursor, NodeCursor templateCursor,
59-
DirectiveRef directiveRef,
60-
ElementBinder transcludedElementBinder,
61-
DirectiveMap directives) {
62-
var anchorName = directiveRef.annotation.selector +
63-
(directiveRef.value != null ? '=' + directiveRef.value : '');
64-
var viewFactory;
65-
var views;
66-
67-
var transcludeCursor = templateCursor.replaceWithAnchor(anchorName);
68-
var domCursorIndex = domCursor.index;
69-
var elementBinders =
70-
_compileView(domCursor, transcludeCursor, transcludedElementBinder, directives);
71-
if (elementBinders == null) elementBinders = [];
72-
73-
viewFactory = new WalkingViewFactory(transcludeCursor.elements, elementBinders, _perf, _expando);
74-
domCursor.index = domCursorIndex;
75-
76-
if (domCursor.isInstance) {
77-
domCursor.insertAnchorBefore(anchorName);
78-
views = [viewFactory([domCursor.current])];
79-
templateCursor.moveNext();
80-
while (domCursor.moveNext() && domCursor.isInstance) {
81-
views.add(viewFactory([domCursor.current]));
82-
templateCursor.remove();
83-
}
84-
} else {
85-
domCursor.replaceWithAnchor(anchorName);
86-
}
87-
88-
return viewFactory;
89-
}
90-
91-
WalkingViewFactory call(List<dom.Node> elements, DirectiveMap directives) {
92-
var timerId;
93-
assert((timerId = _perf.startTimer('ng.compile', _html(elements))) != false);
94-
final List<dom.Node> domElements = elements;
95-
final List<dom.Node> templateElements = cloneElements(domElements);
96-
var elementBinders = _compileView(
97-
new NodeCursor(domElements), new NodeCursor(templateElements),
98-
null, directives);
99-
100-
var viewFactory = new WalkingViewFactory(templateElements,
101-
elementBinders == null ? [] : elementBinders, _perf, _expando);
102-
103-
assert(_perf.stopTimer(timerId) != false);
104-
return viewFactory;
105-
}
4+
ViewFactory call(List<dom.Node> elements, DirectiveMap directives);
1065
}

lib/core_dom/element_binder.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,3 +389,12 @@ class ElementBinderTree {
389389

390390
ElementBinderTree(this.binder, this.subtrees);
391391
}
392+
393+
394+
// Used for the tagging compiler
395+
class TaggedElementBinder {
396+
ElementBinder binder;
397+
int parentBinderOffset;
398+
399+
TaggedElementBinder(this.binder, this.parentBinderOffset);
400+
}

lib/core_dom/module.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ part 'http.dart';
2525
part 'ng_mustache.dart';
2626
part 'node_cursor.dart';
2727
part 'selector.dart';
28+
part 'tagging_compiler.dart';
29+
part 'tagging_view_factory.dart';
2830
part 'template_cache.dart';
2931
part 'tree_sanitizer.dart';
32+
part 'walking_compiler.dart';
3033

3134
class NgCoreDomModule extends Module {
3235
NgCoreDomModule() {

lib/core_dom/tagging_compiler.dart

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
part of angular.core.dom;
2+
3+
@NgInjectableService()
4+
class TaggingCompiler implements Compiler {
5+
final Profiler _perf;
6+
final Expando _expando;
7+
8+
TaggingCompiler(this._perf, this._expando);
9+
10+
List _compileView(
11+
12+
NodeCursor domCursor, NodeCursor templateCursor,
13+
ElementBinder useExistingElementBinder,
14+
DirectiveMap directives) {
15+
List<TaggedElementBinder> elementBinders = [];
16+
if (domCursor.nodeList().length == 0) return null;
17+
18+
19+
do {
20+
var subtrees, binder;
21+
22+
var node = domCursor.nodeList()[0];
23+
24+
// If nodetype is a element, call selector matchElement. If text, call selector.matchText
25+
26+
// TODO: selector will return null for non-useful bindings.
27+
ElementBinder elementBinder = useExistingElementBinder == null
28+
? directives.selector(node)
29+
: useExistingElementBinder;
30+
31+
if (elementBinder.hasTemplate) {
32+
elementBinder.templateViewFactory = _compileTransclusion(elementBinders,
33+
domCursor, templateCursor,
34+
elementBinder.template, elementBinder.templateBinder, directives);
35+
}
36+
37+
if (elementBinder.shouldCompileChildren) {
38+
if (domCursor.descend()) {
39+
templateCursor.descend();
40+
41+
elementBinders.addAll(
42+
_compileView(domCursor, templateCursor, null, directives /*current element list length*/));
43+
44+
domCursor.ascend();
45+
templateCursor.ascend();
46+
}
47+
}
48+
49+
// move this up
50+
if (elementBinder.hasDirectives) {
51+
elementBinders.add(new TaggedElementBinder(elementBinder, -1));
52+
node.classes.add('ng-binding');
53+
binder = elementBinder;
54+
}
55+
} while (templateCursor.microNext() && domCursor.microNext());
56+
57+
return elementBinders;
58+
}
59+
60+
TaggingViewFactory _compileTransclusion(List<TaggedElementBinder> tElementBinders,
61+
NodeCursor domCursor, NodeCursor templateCursor,
62+
DirectiveRef directiveRef,
63+
ElementBinder transcludedElementBinder,
64+
DirectiveMap directives) {
65+
var anchorName = directiveRef.annotation.selector + (directiveRef.value != null ? '=' + directiveRef.value : '');
66+
var viewFactory;
67+
var views;
68+
69+
var transcludeCursor = templateCursor.replaceWithAnchor(anchorName);
70+
var domCursorIndex = domCursor.index;
71+
var elementBinders =
72+
_compileView(domCursor, transcludeCursor, transcludedElementBinder, directives);
73+
if (elementBinders == null) elementBinders = [];
74+
75+
viewFactory = new TaggingViewFactory(transcludeCursor.elements, elementBinders, _perf, _expando);
76+
domCursor.index = domCursorIndex;
77+
78+
if (domCursor.isInstance()) {
79+
domCursor.insertAnchorBefore(anchorName);
80+
views = [viewFactory(domCursor.nodeList())];
81+
domCursor.macroNext();
82+
templateCursor.macroNext();
83+
while (domCursor.isValid() && domCursor.isInstance()) {
84+
views.add(viewFactory(domCursor.nodeList()));
85+
domCursor.macroNext();
86+
templateCursor.remove();
87+
}
88+
} else {
89+
domCursor.replaceWithAnchor(anchorName);
90+
}
91+
92+
return viewFactory;
93+
}
94+
95+
TaggingViewFactory call(List<dom.Node> elements, DirectiveMap directives) {
96+
var timerId;
97+
assert((timerId = _perf.startTimer('ng.compile', _html(elements))) != false);
98+
List<dom.Node> domElements = elements;
99+
List<dom.Node> templateElements = cloneElements(domElements);
100+
List<TaggedElementBinder> elementBinders = _compileView(
101+
new NodeCursor(domElements), new NodeCursor(templateElements),
102+
null, directives);
103+
104+
var viewFactory = new TaggingViewFactory(templateElements,
105+
elementBinders == null ? [] : elementBinders, _perf, _expando);
106+
107+
assert(_perf.stopTimer(timerId) != false);
108+
return viewFactory;
109+
}
110+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
part of angular.core.dom;
2+
3+
class TaggingViewFactory implements ViewFactory {
4+
final List<TaggedElementBinder> elementBinders;
5+
final List<dom.Node> templateElements;
6+
final Profiler _perf;
7+
final Expando _expando;
8+
9+
TaggingViewFactory(this.templateElements, this.elementBinders, this._perf, this._expando);
10+
11+
BoundViewFactory bind(Injector injector) =>
12+
new BoundViewFactory(this, injector);
13+
14+
View call(Injector injector, [List<dom.Node> elements /* TODO: document fragment */]) {
15+
if (elements == null) {
16+
elements = cloneElements(templateElements);
17+
}
18+
var timerId;
19+
try {
20+
assert((timerId = _perf.startTimer('ng.view')) != false);
21+
var view = new View(elements, injector.get(NgAnimate));
22+
_link(view, elements, elementBinders, injector);
23+
return view;
24+
} finally {
25+
assert(_perf.stopTimer(timerId) != false);
26+
}
27+
}
28+
29+
View _link(View view, List<dom.Node> nodeList, List elementBinders, Injector parentInjector) {
30+
31+
32+
var directiveDefsByName = {};
33+
34+
var elementBinderIndex = 0;
35+
for (int i = 0, ii = nodeList.length; i < ii; i++) {
36+
var node = nodeList[i];
37+
print("node: $node ${node.outerHtml}}");
38+
39+
// if node isn't attached to the DOM, create a parent for it.
40+
var parentNode = node.parentNode;
41+
var fakeParent = false;
42+
if (parentNode == null) {
43+
fakeParent = true;
44+
parentNode = new dom.DivElement();
45+
parentNode.append(node);
46+
}
47+
48+
if (node is dom.Element) {
49+
var elts = node.querySelectorAll('.ng-binding');
50+
// HACK: querySelectorAll doesn't return the node.
51+
var startIndex = node.classes.contains('ng-binding') ? -1 : 0;
52+
print("starting at: $startIndex");
53+
for (int j = startIndex, jj = elts.length; j < jj; j++, elementBinderIndex++) {
54+
if (j >= 0) print("elt: ${elts[j]} ${elts[j].outerHtml}");
55+
TaggedElementBinder tagged = elementBinders[elementBinderIndex];
56+
57+
var binder = tagged.binder;
58+
59+
var childInjector = binder != null ? binder.bind(view, parentInjector, j == -1 ? node : elts[j]) : parentInjector;
60+
}
61+
}
62+
63+
if (fakeParent) {
64+
// extract the node from the parentNode.
65+
nodeList[i] = parentNode.nodes[0];
66+
}
67+
68+
// querySelectorAll('.ng-binding') should return a list of nodes in the same order as the elementBinders list.
69+
70+
// keep a injector array --
71+
72+
/*var eb = elementBinders[i];
73+
int index = i;
74+
75+
var binder = eb.binder;
76+
77+
var timerId;
78+
try {
79+
assert((timerId = _perf.startTimer('ng.view.link', _html(node))) != false);
80+
81+
82+
83+
84+
85+
86+
} finally {
87+
assert(_perf.stopTimer(timerId) != false);
88+
}*/
89+
}
90+
return view;
91+
}
92+
}

lib/core_dom/view_factory.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,16 @@ class WalkingViewFactory implements ViewFactory {
5656
}
5757

5858
View _link(View view, List<dom.Node> nodeList, List elementBinders, Injector parentInjector) {
59+
60+
5961
var preRenderedIndexOffset = 0;
6062
var directiveDefsByName = {};
6163

6264
for (int i = 0; i < elementBinders.length; i++) {
65+
// querySelectorAll('.ng-binding') should return a list of nodes in the same order as the elementBinders list.
66+
67+
// keep a injector array --
68+
6369
var eb = elementBinders[i];
6470
int index = eb.offsetIndex;
6571

@@ -100,6 +106,9 @@ class WalkingViewFactory implements ViewFactory {
100106
}
101107
}
102108

109+
110+
111+
103112
/**
104113
* ViewCache is used to cache the compilation of templates into [View]s.
105114
* It can be used synchronously if HTML is known or asynchronously if the

0 commit comments

Comments
 (0)