Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(371)

Unified Diff: dart/pkg/template_binding/lib/src/template_iterator.dart

Issue 336013003: Version 1.5.0-dev.4.14 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dart/pkg/template_binding/lib/src/template.dart ('k') | dart/pkg/template_binding/lib/src/text.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/pkg/template_binding/lib/src/template_iterator.dart
===================================================================
--- dart/pkg/template_binding/lib/src/template_iterator.dart (revision 37358)
+++ dart/pkg/template_binding/lib/src/template_iterator.dart (working copy)
@@ -178,17 +178,19 @@
[List<Bindable> instanceBindings]) {
final bindings = map.bindings;
+ final nodeExt = nodeBind(node);
for (var i = 0; i < bindings.length; i += 2) {
var name = bindings[i];
var tokens = bindings[i + 1];
var value = _processBinding(name, tokens, node, model);
- var binding = nodeBind(node).bind(name, value, oneTime: tokens.onlyOneTime);
+ var binding = nodeExt.bind(name, value, oneTime: tokens.onlyOneTime);
if (binding != null && instanceBindings != null) {
instanceBindings.add(binding);
}
}
+ nodeExt.bindFinished();
if (map is! _TemplateBindingMap) return;
final templateExt = nodeBindFallback(node);
@@ -206,11 +208,7 @@
class _TemplateIterator extends Bindable {
final TemplateBindExtension _templateExt;
- /**
- * Flattened array of tuples:
- * <instanceTerminatorNode, [bindingsSetupByInstance]>
- */
- final List _terminators = [];
+ final List<DocumentFragment> _instances = [];
/** A copy of the last rendered [_presentValue] list state. */
final List _iteratedValue = [];
@@ -332,62 +330,49 @@
_presentValue != null ? _presentValue : []));
}
- Node _getTerminatorAt(int index) {
+ Node _getLastInstanceNode(int index) {
if (index == -1) return _templateElement;
- var terminator = _terminators[index * 2];
+ // TODO(jmesserly): we could avoid this expando lookup by caching the
+ // instance extension instead of the instance.
+ var instance = _instanceExtension[_instances[index]];
+ var terminator = instance._terminator;
+ if (terminator == null) return _getLastInstanceNode(index - 1);
+
if (!isSemanticTemplate(terminator) ||
identical(terminator, _templateElement)) {
return terminator;
}
- var subIter = templateBindFallback(terminator)._iterator;
- if (subIter == null) return terminator;
+ var subtemplateIterator = templateBindFallback(terminator)._iterator;
+ if (subtemplateIterator == null) return terminator;
- return subIter._getTerminatorAt(subIter._terminators.length ~/ 2 - 1);
+ return subtemplateIterator._getLastTemplateNode();
}
- // TODO(rafaelw): If we inserting sequences of instances we can probably
- // avoid lots of calls to _getTerminatorAt(), or cache its result.
- void _insertInstanceAt(int index, DocumentFragment fragment,
- List<Node> instanceNodes, List<Bindable> instanceBindings) {
+ Node _getLastTemplateNode() => _getLastInstanceNode(_instances.length - 1);
- var previousTerminator = _getTerminatorAt(index - 1);
- var terminator = null;
- if (fragment != null) {
- terminator = fragment.lastChild;
- } else if (instanceNodes != null && instanceNodes.isNotEmpty) {
- terminator = instanceNodes.last;
- }
- if (terminator == null) terminator = previousTerminator;
-
- _terminators.insertAll(index * 2, [terminator, instanceBindings]);
+ void _insertInstanceAt(int index, DocumentFragment fragment) {
+ var previousInstanceLast = _getLastInstanceNode(index - 1);
var parent = _templateElement.parentNode;
- var insertBeforeNode = previousTerminator.nextNode;
- if (fragment != null) {
- parent.insertBefore(fragment, insertBeforeNode);
- } else if (instanceNodes != null) {
- for (var node in instanceNodes) {
- parent.insertBefore(node, insertBeforeNode);
- }
- }
+ _instances.insert(index, fragment);
+ parent.insertBefore(fragment, previousInstanceLast.nextNode);
}
- _BoundNodes _extractInstanceAt(int index) {
- var instanceNodes = <Node>[];
- var previousTerminator = _getTerminatorAt(index - 1);
- var terminator = _getTerminatorAt(index);
- var instanceBindings = _terminators[index * 2 + 1];
- _terminators.removeRange(index * 2, index * 2 + 2);
-
+ DocumentFragment _extractInstanceAt(int index) {
+ var previousInstanceLast = _getLastInstanceNode(index - 1);
+ var lastNode = _getLastInstanceNode(index);
var parent = _templateElement.parentNode;
- while (terminator != previousTerminator) {
- var node = previousTerminator.nextNode;
- if (node == terminator) terminator = previousTerminator;
- node.remove();
- instanceNodes.add(node);
+ var instance = _instances.removeAt(index);
+
+ while (lastNode != previousInstanceLast) {
+ var node = previousInstanceLast.nextNode;
+ if (node == lastNode) lastNode = previousInstanceLast;
+
+ instance.append(node..remove());
}
- return new _BoundNodes(instanceNodes, instanceBindings);
+
+ return instance;
}
void _handleSplices(List<ListChangeRecord> splices) {
@@ -416,11 +401,15 @@
}
}
- var instanceCache = new HashMap<Object, _BoundNodes>(equals: identical);
+ // Instance Removals.
+ var instanceCache = new HashMap(equals: identical);
var removeDelta = 0;
for (var splice in splices) {
for (var model in splice.removed) {
- instanceCache[model] = _extractInstanceAt(splice.index + removeDelta);
+ var instance = _extractInstanceAt(splice.index + removeDelta);
+ if (instance != _emptyInstance) {
+ instanceCache[model] = instance;
+ }
}
removeDelta -= splice.addedCount;
@@ -432,22 +421,16 @@
addIndex++) {
var model = _iteratedValue[addIndex];
- var fragment = null;
- var instance = instanceCache.remove(model);
- List instanceBindings;
- List instanceNodes = null;
- if (instance != null && instance.nodes.isNotEmpty) {
- instanceBindings = instance.instanceBindings;
- instanceNodes = instance.nodes;
- } else {
+ DocumentFragment instance = instanceCache.remove(model);
+ if (instance == null) {
try {
- instanceBindings = [];
if (_instanceModelFn != null) {
model = _instanceModelFn(model);
}
- if (model != null) {
- fragment = _templateExt.createInstance(model, delegate,
- instanceBindings);
+ if (model == null) {
+ instance = _emptyInstance;
+ } else {
+ instance = _templateExt.createInstance(model, delegate);
}
} catch (e, s) {
// Dart note: we propagate errors asynchronously here to avoid
@@ -460,33 +443,26 @@
// called from createInstance, but that requires enough refactoring
// that it should be done upstream first. See dartbug.com/17789.
new Completer().completeError(e, s);
+ instance = _emptyInstance;
}
}
- _insertInstanceAt(addIndex, fragment, instanceNodes, instanceBindings);
+ _insertInstanceAt(addIndex, instance);
}
}
for (var instance in instanceCache.values) {
- _closeInstanceBindings(instance.instanceBindings);
+ _closeInstanceBindings(instance);
}
if (_instancePositionChangedFn != null) _reportInstancesMoved(splices);
}
void _reportInstanceMoved(int index) {
- var previousTerminator = _getTerminatorAt(index - 1);
- var terminator = _getTerminatorAt(index);
- if (identical(previousTerminator, terminator)) {
- return; // instance has zero nodes.
- }
+ var instance = _instances[index];
+ if (instance == _emptyInstance) return;
- // We must use the first node of the instance, because any subsequent
- // nodes may have been generated by sub-templates.
- // TODO(rafaelw): This is brittle WRT instance mutation -- e.g. if the
- // first node was removed by script.
- var instance = nodeBind(previousTerminator.nextNode).templateInstance;
- _instancePositionChangedFn(instance, index);
+ _instancePositionChangedFn(nodeBind(instance).templateInstance, index);
}
void _reportInstancesMoved(List<ListChangeRecord> splices) {
@@ -512,15 +488,16 @@
if (offset == 0) return;
- var length = _terminators.length ~/ 2;
+ var length = _instances.length;
while (index < length) {
_reportInstanceMoved(index);
index++;
}
}
- void _closeInstanceBindings(List<Bindable> instanceBindings) {
- for (var binding in instanceBindings) binding.close();
+ void _closeInstanceBindings(DocumentFragment instance) {
+ var bindings = _instanceExtension[instance]._bindings;
+ for (var binding in bindings) binding.close();
}
void _unobserve() {
@@ -533,11 +510,8 @@
if (_closed) return;
_unobserve();
- for (var i = 1; i < _terminators.length; i += 2) {
- _closeInstanceBindings(_terminators[i]);
- }
-
- _terminators.clear();
+ _instances.forEach(_closeInstanceBindings);
+ _instances.clear();
_closeDependencies();
_templateExt._iterator = null;
_closed = true;
« no previous file with comments | « dart/pkg/template_binding/lib/src/template.dart ('k') | dart/pkg/template_binding/lib/src/text.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698