| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 library fn; | 5 library fn; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 import 'dart:mirrors'; | 9 import 'dart:mirrors'; |
| 10 import 'dart:sky' as sky; | 10 import 'dart:sky' as sky; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 String outString = opString.substring(opString.indexOf('.') + 1); | 86 String outString = opString.substring(opString.indexOf('.') + 1); |
| 87 _trace('_sync($outString) $key'); | 87 _trace('_sync($outString) $key'); |
| 88 } | 88 } |
| 89 | 89 |
| 90 void removeChild(UINode node) { | 90 void removeChild(UINode node) { |
| 91 _traceSync(_SyncOperation.REMOVAL, node._key); | 91 _traceSync(_SyncOperation.REMOVAL, node._key); |
| 92 node._remove(); | 92 node._remove(); |
| 93 } | 93 } |
| 94 | 94 |
| 95 // Returns the child which should be retained as the child of this node. | 95 // Returns the child which should be retained as the child of this node. |
| 96 UINode _syncChild(UINode node, UINode oldNode, dynamic slot) { | 96 UINode syncChild(UINode node, UINode oldNode, dynamic slot) { |
| 97 assert(node != null); | |
| 98 assert(oldNode == null || node._key == oldNode._key); | |
| 99 | 97 |
| 100 if (node == oldNode) { | 98 if (node == oldNode) { |
| 101 _traceSync(_SyncOperation.IDENTICAL, node._key); | 99 _traceSync(_SyncOperation.IDENTICAL, node == null ? '*null*' : node._key); |
| 102 return node; // Nothing to do. Subtrees must be identical. | 100 return node; // Nothing to do. Subtrees must be identical. |
| 103 } | 101 } |
| 104 | 102 |
| 103 if (node == null) { |
| 104 // the child in this slot has gone away |
| 105 removeChild(oldNode); |
| 106 return null; |
| 107 } |
| 108 assert(oldNode == null || node._key == oldNode._key); |
| 109 |
| 105 // TODO(rafaelw): This eagerly removes the old DOM. It may be that a | 110 // TODO(rafaelw): This eagerly removes the old DOM. It may be that a |
| 106 // new component was built that could re-use some of it. Consider | 111 // new component was built that could re-use some of it. Consider |
| 107 // syncing the new VDOM against the old one. | 112 // syncing the new VDOM against the old one. |
| 108 if (oldNode != null && node._key != oldNode._key) { | 113 if (oldNode != null && node._key != oldNode._key) { |
| 109 removeChild(oldNode); | 114 removeChild(oldNode); |
| 110 } | 115 } |
| 111 | 116 |
| 112 if (node._willSync(oldNode)) { | 117 if (node._willSync(oldNode)) { |
| 113 _traceSync(_SyncOperation.STATEFUL, node._key); | 118 _traceSync(_SyncOperation.STATEFUL, node._key); |
| 114 oldNode._sync(node, slot); | 119 oldNode._sync(node, slot); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 134 } | 139 } |
| 135 } | 140 } |
| 136 | 141 |
| 137 abstract class ContentNode extends UINode { | 142 abstract class ContentNode extends UINode { |
| 138 UINode content; | 143 UINode content; |
| 139 | 144 |
| 140 ContentNode(UINode content) : this.content = content, super(key: content._key)
; | 145 ContentNode(UINode content) : this.content = content, super(key: content._key)
; |
| 141 | 146 |
| 142 void _sync(UINode old, dynamic slot) { | 147 void _sync(UINode old, dynamic slot) { |
| 143 UINode oldContent = old == null ? null : (old as ContentNode).content; | 148 UINode oldContent = old == null ? null : (old as ContentNode).content; |
| 144 content = _syncChild(content, oldContent, slot); | 149 content = syncChild(content, oldContent, slot); |
| 145 assert(content.root != null); | 150 assert(content.root != null); |
| 146 root = content.root; | 151 root = content.root; |
| 147 } | 152 } |
| 148 | 153 |
| 149 void _remove() { | 154 void _remove() { |
| 150 if (content != null) | 155 if (content != null) |
| 151 removeChild(content); | 156 removeChild(content); |
| 152 super._remove(); | 157 super._remove(); |
| 153 } | 158 } |
| 154 } | 159 } |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 | 439 |
| 435 var oldChildren = old.children; | 440 var oldChildren = old.children; |
| 436 var oldStartIndex = 0; | 441 var oldStartIndex = 0; |
| 437 var oldEndIndex = oldChildren.length; | 442 var oldEndIndex = oldChildren.length; |
| 438 | 443 |
| 439 RenderCSS nextSibling = null; | 444 RenderCSS nextSibling = null; |
| 440 UINode currentNode = null; | 445 UINode currentNode = null; |
| 441 UINode oldNode = null; | 446 UINode oldNode = null; |
| 442 | 447 |
| 443 void sync(int atIndex) { | 448 void sync(int atIndex) { |
| 444 children[atIndex] = _syncChild(currentNode, oldNode, nextSibling); | 449 children[atIndex] = syncChild(currentNode, oldNode, nextSibling); |
| 445 assert(children[atIndex] != null); | 450 assert(children[atIndex] != null); |
| 446 } | 451 } |
| 447 | 452 |
| 448 // Scan backwards from end of list while nodes can be directly synced | 453 // Scan backwards from end of list while nodes can be directly synced |
| 449 // without reordering. | 454 // without reordering. |
| 450 while (endIndex > startIndex && oldEndIndex > oldStartIndex) { | 455 while (endIndex > startIndex && oldEndIndex > oldStartIndex) { |
| 451 currentNode = children[endIndex - 1]; | 456 currentNode = children[endIndex - 1]; |
| 452 oldNode = oldChildren[oldEndIndex - 1]; | 457 oldNode = oldChildren[oldEndIndex - 1]; |
| 453 | 458 |
| 454 if (currentNode._key != oldNode._key) { | 459 if (currentNode._key != oldNode._key) { |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 if (oldBuilt == null) | 897 if (oldBuilt == null) |
| 893 _enqueueDidMount(this); | 898 _enqueueDidMount(this); |
| 894 | 899 |
| 895 int lastOrder = _currentOrder; | 900 int lastOrder = _currentOrder; |
| 896 _currentOrder = _order; | 901 _currentOrder = _order; |
| 897 _currentlyBuilding = this; | 902 _currentlyBuilding = this; |
| 898 _built = build(); | 903 _built = build(); |
| 899 _currentlyBuilding = null; | 904 _currentlyBuilding = null; |
| 900 _currentOrder = lastOrder; | 905 _currentOrder = lastOrder; |
| 901 | 906 |
| 902 _built = _syncChild(_built, oldBuilt, slot); | 907 _built = syncChild(_built, oldBuilt, slot); |
| 903 _dirty = false; | 908 _dirty = false; |
| 904 root = _built.root; | 909 root = _built.root; |
| 905 assert(root != null); | 910 assert(root != null); |
| 906 } | 911 } |
| 907 | 912 |
| 908 void _buildIfDirty() { | 913 void _buildIfDirty() { |
| 909 if (!_dirty || _defunct) | 914 if (!_dirty || _defunct) |
| 910 return; | 915 return; |
| 911 | 916 |
| 912 _trace('$_key rebuilding...'); | 917 _trace('$_key rebuilding...'); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 assert(root.parent == _host); | 955 assert(root.parent == _host); |
| 951 } | 956 } |
| 952 } | 957 } |
| 953 | 958 |
| 954 class Text extends Component { | 959 class Text extends Component { |
| 955 Text(this.data) : super(key: '*text*'); | 960 Text(this.data) : super(key: '*text*'); |
| 956 final String data; | 961 final String data; |
| 957 bool get interchangeable => true; | 962 bool get interchangeable => true; |
| 958 UINode build() => new Paragraph(children: [new TextFragment(data)]); | 963 UINode build() => new Paragraph(children: [new TextFragment(data)]); |
| 959 } | 964 } |
| OLD | NEW |