Skip to content

Commit 211f63c

Browse files
vsavkindsalsbury
authored andcommitted
refactor(compiler): rename TaggingCompiler into Compiler and TaggingViewFactory into ViewFactory
Remove Compiler and ViewFactory interfaces because they have only one implementation each. Closes dart-archive#1333
1 parent c729560 commit 211f63c

File tree

6 files changed

+347
-363
lines changed

6 files changed

+347
-363
lines changed

lib/core_dom/compiler.dart

Lines changed: 179 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,182 @@
11
part of angular.core.dom_internal;
22

3-
abstract class Compiler implements Function {
4-
ViewFactory call(List<dom.Node> elements, DirectiveMap directives);
3+
@Injectable()
4+
class Compiler implements Function {
5+
final Profiler _perf;
6+
final Expando _expando;
7+
8+
Compiler(this._perf, this._expando);
9+
10+
ViewFactory call(List<dom.Node> elements, DirectiveMap directives) {
11+
var timerId;
12+
assert((timerId = _perf.startTimer('ng.compile', _html(elements))) != false);
13+
final elementBinders = <TaggedElementBinder>[];
14+
_compileView(
15+
new NodeCursor(elements),
16+
null, directives, -1, null, elementBinders, true);
17+
18+
var viewFactory = new ViewFactory(
19+
elements, _removeUnusedBinders(elementBinders), _perf);
20+
21+
assert(_perf.stopTimer(timerId) != false);
22+
return viewFactory;
23+
}
24+
25+
ElementBinder _elementBinderForNode(NodeCursor domCursor,
26+
ElementBinder useExistingElementBinder,
27+
DirectiveMap directives,
28+
List elementBinders) {
29+
var node = domCursor.current;
30+
31+
if (node.nodeType == dom.Node.ELEMENT_NODE) {
32+
// If the node is an element, call selector matchElement.
33+
// If text, call selector.matchText
34+
35+
ElementBinder elementBinder = useExistingElementBinder == null ?
36+
directives.selector.matchElement(node) : useExistingElementBinder;
37+
38+
if (elementBinder.hasTemplate) {
39+
var templateBinder = elementBinder as TemplateElementBinder;
40+
templateBinder.templateViewFactory = _compileTransclusion(
41+
domCursor, templateBinder.template,
42+
templateBinder.templateBinder, directives);
43+
}
44+
return elementBinder;
45+
} else if (node.nodeType == dom.Node.TEXT_NODE) {
46+
return directives.selector.matchText(node);
47+
}
48+
return null;
49+
}
50+
51+
void _compileNode(NodeCursor domCursor,
52+
ElementBinder elementBinder,
53+
DirectiveMap directives,
54+
List elementBinders,
55+
int parentElementBinderOffset,
56+
bool isTopLevel,
57+
TaggedElementBinder directParentElementBinder) {
58+
var node = domCursor.current;
59+
if (node.nodeType == dom.Node.ELEMENT_NODE) {
60+
TaggedElementBinder taggedElementBinder;
61+
int taggedElementBinderIndex;
62+
if (elementBinder.hasDirectivesOrEvents || elementBinder.hasTemplate) {
63+
taggedElementBinder = _addBinder(elementBinders,
64+
new TaggedElementBinder(elementBinder, parentElementBinderOffset, isTopLevel));
65+
taggedElementBinderIndex = elementBinders.length - 1;
66+
node.classes.add('ng-binding');
67+
} else {
68+
taggedElementBinder = null;
69+
taggedElementBinderIndex = parentElementBinderOffset;
70+
}
71+
72+
if (elementBinder.shouldCompileChildren) {
73+
if (domCursor.descend()) {
74+
var addedDummy = false;
75+
if (taggedElementBinder == null) {
76+
addedDummy = true;
77+
// add a dummy to the list which may be removed later.
78+
taggedElementBinder = _addBinder(elementBinders,
79+
new TaggedElementBinder(null, parentElementBinderOffset, isTopLevel));
80+
}
81+
82+
_compileView(domCursor, null, directives, taggedElementBinderIndex,
83+
taggedElementBinder, elementBinders, false);
84+
85+
if (addedDummy && !taggedElementBinder.isDummy) {
86+
// We are keeping the element binder, so add the class
87+
// to the DOM node as well.
88+
//
89+
// To avoid array chrun, we remove all dummy binders at the
90+
// end of the compilation process.
91+
node.classes.add('ng-binding');
92+
}
93+
domCursor.ascend();
94+
}
95+
}
96+
} else if (node.nodeType == dom.Node.TEXT_NODE ||
97+
node.nodeType == dom.Node.COMMENT_NODE) {
98+
if (elementBinder != null &&
99+
elementBinder.hasDirectivesOrEvents &&
100+
directParentElementBinder != null) {
101+
directParentElementBinder.addText(
102+
new TaggedTextBinder(elementBinder, domCursor.index));
103+
} else if (isTopLevel) {
104+
// Always add an elementBinder for top-level text.
105+
_addBinder(elementBinders,
106+
new TaggedElementBinder(elementBinder, parentElementBinderOffset, isTopLevel));
107+
}
108+
} else {
109+
throw "Unsupported node type for $node: [${node.nodeType}]";
110+
}
111+
}
112+
113+
List<TaggedElementBinder> _compileView(NodeCursor domCursor,
114+
ElementBinder useExistingElementBinder,
115+
DirectiveMap directives,
116+
int parentElementBinderOffset,
117+
TaggedElementBinder directParentElementBinder,
118+
List<TaggedElementBinder> elementBinders,
119+
bool isTopLevel) {
120+
assert(parentElementBinderOffset != null);
121+
assert(parentElementBinderOffset < elementBinders.length);
122+
if (domCursor.current == null) return null;
123+
124+
do {
125+
_compileNode(domCursor,
126+
_elementBinderForNode(domCursor, useExistingElementBinder, directives, elementBinders),
127+
directives, elementBinders, parentElementBinderOffset,
128+
isTopLevel, directParentElementBinder);
129+
} while (domCursor.moveNext());
130+
131+
return elementBinders;
132+
}
133+
134+
ViewFactory _compileTransclusion(
135+
NodeCursor templateCursor,
136+
DirectiveRef directiveRef,
137+
ElementBinder transcludedElementBinder,
138+
DirectiveMap directives) {
139+
var anchorName = directiveRef.annotation.selector +
140+
(directiveRef.value != null ? '=' + directiveRef.value : '');
141+
142+
var transcludeCursor = templateCursor.replaceWithAnchor(anchorName);
143+
var elementBinders = [];
144+
_compileView(transcludeCursor, transcludedElementBinder,
145+
directives, -1, null, elementBinders, true);
146+
147+
var viewFactory = new ViewFactory(transcludeCursor.elements,
148+
_removeUnusedBinders(elementBinders), _perf);
149+
150+
return viewFactory;
151+
}
152+
153+
List<TaggedElementBinder> _removeUnusedBinders(List<TaggedElementBinder> binders) {
154+
// In order to support text nodes with directiveless parents, we
155+
// add dummy ElementBinders to the list. After the entire template
156+
// has been compiled, we remove the dummies and update the offset indices
157+
final output = <TaggedElementBinder>[];
158+
final List<int> offsetMap = [];
159+
int outputIndex = 0;
160+
161+
for (var i = 0; i < binders.length; i++) {
162+
TaggedElementBinder binder = binders[i];
163+
if (binder.isDummy) {
164+
offsetMap.add(-2);
165+
} else {
166+
if (binder.parentBinderOffset != -1) {
167+
binder.parentBinderOffset = offsetMap[binder.parentBinderOffset];
168+
}
169+
assert(binder.parentBinderOffset != -2);
170+
output.add(binder);
171+
offsetMap.add(outputIndex++);
172+
}
173+
}
174+
return output;
175+
}
176+
}
177+
178+
TaggedElementBinder _addBinder(List list, TaggedElementBinder binder) {
179+
assert(binder.parentBinderOffset != list.length); // Do not point to yourself!
180+
list.add(binder);
181+
return binder;
5182
}

lib/core_dom/module_internal.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ part 'node_cursor.dart';
4343
part 'selector.dart';
4444
part 'shadow_dom_component_factory.dart';
4545
part 'shadowless_shadow_root.dart';
46-
part 'tagging_compiler.dart';
47-
part 'tagging_view_factory.dart';
4846
part 'template_cache.dart';
4947
part 'transcluding_component_factory.dart';
5048
part 'tree_sanitizer.dart';
@@ -68,7 +66,7 @@ class CoreDomModule extends Module {
6866
bind(TextMustache);
6967
bind(AttrMustache);
7068

71-
bind(Compiler, toImplementation: TaggingCompiler);
69+
bind(Compiler);
7270
bind(CompilerConfig);
7371

7472
bind(ComponentFactory, toInstanceOf: SHADOW_DOM_COMPONENT_FACTORY_KEY);

lib/core_dom/tagging_compiler.dart

Lines changed: 0 additions & 182 deletions
This file was deleted.

0 commit comments

Comments
 (0)