This repository has been archived by the owner on Feb 22, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 248
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(compiler): Initial TagggingCompiler implementation
- Loading branch information
Showing
8 changed files
with
346 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,106 +1,5 @@ | ||
part of angular.core.dom; | ||
|
||
abstract class Compiler implements Function { | ||
WalkingViewFactory call(List<dom.Node> elements, DirectiveMap directives); | ||
} | ||
|
||
@NgInjectableService() | ||
class WalkingCompiler implements Compiler { | ||
final Profiler _perf; | ||
final Expando _expando; | ||
|
||
WalkingCompiler(this._perf, this._expando); | ||
|
||
List<ElementBinderTreeRef> _compileView(NodeCursor domCursor, NodeCursor templateCursor, | ||
ElementBinder existingElementBinder, | ||
DirectiveMap directives) { | ||
if (domCursor.current == null) return null; | ||
|
||
List<ElementBinderTreeRef> elementBinders = null; // don't pre-create to create sparse tree and prevent GC pressure. | ||
|
||
do { | ||
var subtrees, binder; | ||
|
||
ElementBinder elementBinder = existingElementBinder == null | ||
? directives.selector(domCursor.current) | ||
: existingElementBinder; | ||
|
||
if (elementBinder.hasTemplate) { | ||
elementBinder.templateViewFactory = _compileTransclusion( | ||
domCursor, templateCursor, | ||
elementBinder.template, elementBinder.templateBinder, directives); | ||
} | ||
|
||
if (elementBinder.shouldCompileChildren) { | ||
if (domCursor.descend()) { | ||
templateCursor.descend(); | ||
|
||
subtrees = | ||
_compileView(domCursor, templateCursor, null, directives); | ||
|
||
domCursor.ascend(); | ||
templateCursor.ascend(); | ||
} | ||
} | ||
|
||
if (elementBinder.hasDirectives) { | ||
binder = elementBinder; | ||
} | ||
|
||
if (elementBinders == null) elementBinders = []; | ||
elementBinders.add(new ElementBinderTreeRef(templateCursor.index, new ElementBinderTree(binder, subtrees))); | ||
} while (templateCursor.moveNext() && domCursor.moveNext()); | ||
|
||
return elementBinders; | ||
} | ||
|
||
WalkingViewFactory _compileTransclusion( | ||
NodeCursor domCursor, NodeCursor templateCursor, | ||
DirectiveRef directiveRef, | ||
ElementBinder transcludedElementBinder, | ||
DirectiveMap directives) { | ||
var anchorName = directiveRef.annotation.selector + | ||
(directiveRef.value != null ? '=' + directiveRef.value : ''); | ||
var viewFactory; | ||
var views; | ||
|
||
var transcludeCursor = templateCursor.replaceWithAnchor(anchorName); | ||
var domCursorIndex = domCursor.index; | ||
var elementBinders = | ||
_compileView(domCursor, transcludeCursor, transcludedElementBinder, directives); | ||
if (elementBinders == null) elementBinders = []; | ||
|
||
viewFactory = new WalkingViewFactory(transcludeCursor.elements, elementBinders, _perf, _expando); | ||
domCursor.index = domCursorIndex; | ||
|
||
if (domCursor.isInstance) { | ||
domCursor.insertAnchorBefore(anchorName); | ||
views = [viewFactory([domCursor.current])]; | ||
templateCursor.moveNext(); | ||
while (domCursor.moveNext() && domCursor.isInstance) { | ||
views.add(viewFactory([domCursor.current])); | ||
templateCursor.remove(); | ||
} | ||
} else { | ||
domCursor.replaceWithAnchor(anchorName); | ||
} | ||
|
||
return viewFactory; | ||
} | ||
|
||
WalkingViewFactory call(List<dom.Node> elements, DirectiveMap directives) { | ||
var timerId; | ||
assert((timerId = _perf.startTimer('ng.compile', _html(elements))) != false); | ||
final List<dom.Node> domElements = elements; | ||
final List<dom.Node> templateElements = cloneElements(domElements); | ||
var elementBinders = _compileView( | ||
new NodeCursor(domElements), new NodeCursor(templateElements), | ||
null, directives); | ||
|
||
var viewFactory = new WalkingViewFactory(templateElements, | ||
elementBinders == null ? [] : elementBinders, _perf, _expando); | ||
|
||
assert(_perf.stopTimer(timerId) != false); | ||
return viewFactory; | ||
} | ||
ViewFactory call(List<dom.Node> elements, DirectiveMap directives); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
part of angular.core.dom; | ||
|
||
@NgInjectableService() | ||
class TaggingCompiler implements Compiler { | ||
final Profiler _perf; | ||
final Expando _expando; | ||
|
||
TaggingCompiler(this._perf, this._expando); | ||
|
||
List _compileView( | ||
|
||
NodeCursor domCursor, NodeCursor templateCursor, | ||
ElementBinder useExistingElementBinder, | ||
DirectiveMap directives) { | ||
List<TaggedElementBinder> elementBinders = []; | ||
if (domCursor.nodeList().length == 0) return null; | ||
|
||
|
||
do { | ||
var subtrees, binder; | ||
|
||
var node = domCursor.nodeList()[0]; | ||
|
||
// If nodetype is a element, call selector matchElement. If text, call selector.matchText | ||
|
||
// TODO: selector will return null for non-useful bindings. | ||
ElementBinder elementBinder = useExistingElementBinder == null | ||
? directives.selector(node) | ||
: useExistingElementBinder; | ||
|
||
if (elementBinder.hasTemplate) { | ||
elementBinder.templateViewFactory = _compileTransclusion(elementBinders, | ||
domCursor, templateCursor, | ||
elementBinder.template, elementBinder.templateBinder, directives); | ||
} | ||
|
||
if (elementBinder.shouldCompileChildren) { | ||
if (domCursor.descend()) { | ||
templateCursor.descend(); | ||
|
||
elementBinders.addAll( | ||
_compileView(domCursor, templateCursor, null, directives /*current element list length*/)); | ||
|
||
domCursor.ascend(); | ||
templateCursor.ascend(); | ||
} | ||
} | ||
|
||
// move this up | ||
if (elementBinder.hasDirectives) { | ||
elementBinders.add(new TaggedElementBinder(elementBinder, -1)); | ||
node.classes.add('ng-binding'); | ||
binder = elementBinder; | ||
} | ||
} while (templateCursor.microNext() && domCursor.microNext()); | ||
|
||
return elementBinders; | ||
} | ||
|
||
TaggingViewFactory _compileTransclusion(List<TaggedElementBinder> tElementBinders, | ||
NodeCursor domCursor, NodeCursor templateCursor, | ||
DirectiveRef directiveRef, | ||
ElementBinder transcludedElementBinder, | ||
DirectiveMap directives) { | ||
var anchorName = directiveRef.annotation.selector + (directiveRef.value != null ? '=' + directiveRef.value : ''); | ||
var viewFactory; | ||
var views; | ||
|
||
var transcludeCursor = templateCursor.replaceWithAnchor(anchorName); | ||
var domCursorIndex = domCursor.index; | ||
var elementBinders = | ||
_compileView(domCursor, transcludeCursor, transcludedElementBinder, directives); | ||
if (elementBinders == null) elementBinders = []; | ||
|
||
viewFactory = new TaggingViewFactory(transcludeCursor.elements, elementBinders, _perf, _expando); | ||
domCursor.index = domCursorIndex; | ||
|
||
if (domCursor.isInstance()) { | ||
domCursor.insertAnchorBefore(anchorName); | ||
views = [viewFactory(domCursor.nodeList())]; | ||
domCursor.macroNext(); | ||
templateCursor.macroNext(); | ||
while (domCursor.isValid() && domCursor.isInstance()) { | ||
views.add(viewFactory(domCursor.nodeList())); | ||
domCursor.macroNext(); | ||
templateCursor.remove(); | ||
} | ||
} else { | ||
domCursor.replaceWithAnchor(anchorName); | ||
} | ||
|
||
return viewFactory; | ||
} | ||
|
||
TaggingViewFactory call(List<dom.Node> elements, DirectiveMap directives) { | ||
var timerId; | ||
assert((timerId = _perf.startTimer('ng.compile', _html(elements))) != false); | ||
List<dom.Node> domElements = elements; | ||
List<dom.Node> templateElements = cloneElements(domElements); | ||
List<TaggedElementBinder> elementBinders = _compileView( | ||
new NodeCursor(domElements), new NodeCursor(templateElements), | ||
null, directives); | ||
|
||
var viewFactory = new TaggingViewFactory(templateElements, | ||
elementBinders == null ? [] : elementBinders, _perf, _expando); | ||
|
||
assert(_perf.stopTimer(timerId) != false); | ||
return viewFactory; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
part of angular.core.dom; | ||
|
||
class TaggingViewFactory implements ViewFactory { | ||
final List<TaggedElementBinder> elementBinders; | ||
final List<dom.Node> templateElements; | ||
final Profiler _perf; | ||
final Expando _expando; | ||
|
||
TaggingViewFactory(this.templateElements, this.elementBinders, this._perf, this._expando); | ||
|
||
BoundViewFactory bind(Injector injector) => | ||
new BoundViewFactory(this, injector); | ||
|
||
View call(Injector injector, [List<dom.Node> elements /* TODO: document fragment */]) { | ||
if (elements == null) { | ||
elements = cloneElements(templateElements); | ||
} | ||
var timerId; | ||
try { | ||
assert((timerId = _perf.startTimer('ng.view')) != false); | ||
var view = new View(elements, injector.get(NgAnimate)); | ||
_link(view, elements, elementBinders, injector); | ||
return view; | ||
} finally { | ||
assert(_perf.stopTimer(timerId) != false); | ||
} | ||
} | ||
|
||
View _link(View view, List<dom.Node> nodeList, List elementBinders, Injector parentInjector) { | ||
|
||
|
||
var directiveDefsByName = {}; | ||
|
||
var elementBinderIndex = 0; | ||
for (int i = 0, ii = nodeList.length; i < ii; i++) { | ||
var node = nodeList[i]; | ||
print("node: $node ${node.outerHtml}}"); | ||
|
||
// if node isn't attached to the DOM, create a parent for it. | ||
var parentNode = node.parentNode; | ||
var fakeParent = false; | ||
if (parentNode == null) { | ||
fakeParent = true; | ||
parentNode = new dom.DivElement(); | ||
parentNode.append(node); | ||
} | ||
|
||
if (node is dom.Element) { | ||
var elts = node.querySelectorAll('.ng-binding'); | ||
// HACK: querySelectorAll doesn't return the node. | ||
var startIndex = node.classes.contains('ng-binding') ? -1 : 0; | ||
print("starting at: $startIndex"); | ||
for (int j = startIndex, jj = elts.length; j < jj; j++, elementBinderIndex++) { | ||
if (j >= 0) print("elt: ${elts[j]} ${elts[j].outerHtml}"); | ||
TaggedElementBinder tagged = elementBinders[elementBinderIndex]; | ||
|
||
var binder = tagged.binder; | ||
|
||
var childInjector = binder != null ? binder.bind(view, parentInjector, j == -1 ? node : elts[j]) : parentInjector; | ||
} | ||
} | ||
|
||
if (fakeParent) { | ||
// extract the node from the parentNode. | ||
nodeList[i] = parentNode.nodes[0]; | ||
} | ||
|
||
// querySelectorAll('.ng-binding') should return a list of nodes in the same order as the elementBinders list. | ||
|
||
// keep a injector array -- | ||
|
||
/*var eb = elementBinders[i]; | ||
int index = i; | ||
var binder = eb.binder; | ||
var timerId; | ||
try { | ||
assert((timerId = _perf.startTimer('ng.view.link', _html(node))) != false); | ||
} finally { | ||
assert(_perf.stopTimer(timerId) != false); | ||
}*/ | ||
} | ||
return view; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.