From 7cb2b7114eec692b16ebfac1492b50fb9212970b Mon Sep 17 00:00:00 2001 From: Hixie Date: Wed, 20 May 2015 15:56:10 -0700 Subject: [PATCH] [Effen] Move responsibility for inserting nodes to the OneChildListRenderNodeWrapper. Before, OneChildListRenderNodeWrappers were responsible for removing the child nodes' RenderCSS nodes from their containers, and for moving those around when nodes were reordered. Now, they're also responsible for adding them. R=abarth@chromium.org Review URL: https://codereview.chromium.org/1145953003 --- sdk/lib/framework/fn.dart | 65 ++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/sdk/lib/framework/fn.dart b/sdk/lib/framework/fn.dart index dc54b76f1c6..eab821ab988 100644 --- a/sdk/lib/framework/fn.dart +++ b/sdk/lib/framework/fn.dart @@ -6,6 +6,7 @@ library fn; import 'dart:async'; import 'dart:collection'; +import 'dart:mirrors'; import 'dart:sky' as sky; import 'reflect.dart' as reflect; import 'layout.dart'; @@ -41,7 +42,9 @@ abstract class UINode { bool get interchangeable => false; // if true, then keys can be duplicated - void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore); + void _sync(UINode old, dynamic slot); + // 'slot' is the identifier that the parent RenderNodeWrapper uses to know + // where to put this descendant void _remove() { _defunct = true; @@ -50,6 +53,13 @@ abstract class UINode { } void handleRemoved() { } + UINode findAncestor(Type targetType) { + var ancestor = _parent; + while (ancestor != null && !reflectClass(ancestor.runtimeType).isSubtypeOf(reflectClass(targetType))) + ancestor = ancestor._parent; + return ancestor; + } + int _nodeDepth; void _ensureDepth() { if (_nodeDepth == null) { @@ -85,9 +95,8 @@ abstract class UINode { } // Returns the child which should be retained as the child of this node. - UINode _syncChild(UINode node, UINode oldNode, RenderCSSContainer host, - RenderCSS insertBefore) { - + UINode _syncChild(UINode node, UINode oldNode, dynamic slot) { + assert(node != null); assert(oldNode == null || node._key == oldNode._key); if (node == oldNode) { @@ -104,7 +113,7 @@ abstract class UINode { if (node._willSync(oldNode)) { _traceSync(_SyncOperation.STATEFUL, node._key); - oldNode._sync(node, host, insertBefore); + oldNode._sync(node, slot); node._defunct = true; assert(oldNode._root is RenderCSS); return oldNode; @@ -118,7 +127,7 @@ abstract class UINode { } else { _traceSync(_SyncOperation.STATELESS, node._key); } - node._sync(oldNode, host, insertBefore); + node._sync(oldNode, slot); if (oldNode != null) oldNode._defunct = true; @@ -132,9 +141,9 @@ abstract class ContentNode extends UINode { ContentNode(UINode content) : this.content = content, super(key: content._key); - void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore) { + void _sync(UINode old, dynamic slot) { UINode oldContent = old == null ? null : (old as ContentNode).content; - content = _syncChild(content, oldContent, host, insertBefore); + content = _syncChild(content, oldContent, slot); assert(content._root != null); _root = content._root; } @@ -266,12 +275,11 @@ class EventListenerNode extends ContentNode { } } - void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore) { + void _sync(UINode old, dynamic slot) { for (var type in listeners.keys) { _ensureDocumentListener(type); } - - super._sync(old, host, insertBefore); + super._sync(old, slot); } } @@ -301,11 +309,15 @@ abstract class RenderNodeWrapper extends UINode { RenderCSS _createNode(); RenderNodeWrapper get _emptyNode; - void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore) { + void insert(RenderNodeWrapper child, dynamic slot); + + void _sync(UINode old, dynamic slot) { if (old == null) { _root = _createNode(); assert(_root != null); - host.add(_root, before: insertBefore); + var ancestor = findAncestor(RenderNodeWrapper); + if (ancestor is RenderNodeWrapper) + ancestor.insert(this, slot); old = _emptyNode; } else { _root = old._root; @@ -364,6 +376,9 @@ final List _emptyList = new List(); abstract class OneChildListRenderNodeWrapper extends RenderNodeWrapper { + // In OneChildListRenderNodeWrapper subclasses, slots are RenderCSS nodes + // to use as the "insert before" sibling in RenderCSSContainer.add() calls + final List children; OneChildListRenderNodeWrapper({ @@ -380,6 +395,11 @@ abstract class OneChildListRenderNodeWrapper extends RenderNodeWrapper { assert(!_debugHasDuplicateIds()); } + void insert(RenderNodeWrapper child, dynamic slot) { + assert(slot == null || slot is RenderCSS); + _root.add(child._root, before: slot); + } + void _remove() { assert(children != null); for (var child in children) { @@ -423,7 +443,7 @@ abstract class OneChildListRenderNodeWrapper extends RenderNodeWrapper { UINode oldNode = null; void sync(int atIndex) { - children[atIndex] = _syncChild(currentNode, oldNode, _root, nextSibling); + children[atIndex] = _syncChild(currentNode, oldNode, nextSibling); assert(children[atIndex] != null); } @@ -482,8 +502,10 @@ abstract class OneChildListRenderNodeWrapper extends RenderNodeWrapper { oldNodeIdMap[currentNode._key] = null; // mark it reordered assert(_root is RenderCSSContainer); assert(oldNode._root is RenderCSSContainer); + old._root.remove(oldNode._root); _root.add(oldNode._root, before: nextSibling); + return true; } @@ -780,6 +802,7 @@ abstract class Component extends UINode { static Component _currentlyBuilding; List _mountCallbacks; List _unmountCallbacks; + dynamic _slot; // cached slot from the last time we were synced void onDidMount(Function fn) { if (_mountCallbacks == null) @@ -852,12 +875,14 @@ abstract class Component extends UINode { * 3) Syncing against an old version * assert(_built == null && old != null) */ - void _sync(UINode old, RenderCSSContainer host, RenderCSS insertBefore) { + void _sync(UINode old, dynamic slot) { assert(!_defunct); assert(_built == null || old == null); Component oldComponent = old as Component; + _slot = slot; + var oldBuilt; if (oldComponent == null) { oldBuilt = _built; @@ -876,7 +901,7 @@ abstract class Component extends UINode { _currentlyBuilding = null; _currentOrder = lastOrder; - _built = _syncChild(_built, oldBuilt, host, insertBefore); + _built = _syncChild(_built, oldBuilt, slot); _dirty = false; _root = _built._root; assert(_root != null); @@ -887,7 +912,8 @@ abstract class Component extends UINode { return; _trace('$_key rebuilding...'); - _sync(null, _root.parent, _root.parent.childAfter(_root)); + assert(_root != null); + _sync(null, _slot); } void scheduleBuild() { @@ -920,7 +946,10 @@ abstract class App extends Component { return; _trace('$_key rebuilding...'); - _sync(null, _host, _root); + _sync(null, null); + if (_root.parent == null) + _host.add(_root); + assert(_root.parent == _host); } }