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

Side by Side Diff: runtime/observatory/lib/src/elements/containers/virtual_tree.dart

Issue 2968813002: Avoid Stack Overflows during VirtualTree expansion (Closed)
Patch Set: Added missing tests Created 3 years, 5 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async'; 5 import 'dart:async';
6 import 'dart:html'; 6 import 'dart:html';
7 import 'dart:collection';
7 import 'dart:math' as Math; 8 import 'dart:math' as Math;
8 import 'package:observatory/src/elements/containers/virtual_collection.dart'; 9 import 'package:observatory/src/elements/containers/virtual_collection.dart';
9 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; 10 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
10 import 'package:observatory/src/elements/helpers/tag.dart'; 11 import 'package:observatory/src/elements/helpers/tag.dart';
11 12
12 typedef HtmlElement VirtualTreeCreateCallback( 13 typedef HtmlElement VirtualTreeCreateCallback(
13 toggle({bool autoToggleSingleChildNodes, bool autoToggleWholeTree})); 14 toggle({bool autoToggleSingleChildNodes, bool autoToggleWholeTree}));
14 typedef void VirtualTreeUpdateCallback(HtmlElement el, dynamic item, int depth); 15 typedef void VirtualTreeUpdateCallback(HtmlElement el, dynamic item, int depth);
15 typedef Iterable<dynamic> VritualTreeGetChildrenCallback(dynamic value); 16 typedef Iterable<dynamic> VritualTreeGetChildrenCallback(dynamic value);
16 17
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 83
83 bool isExpanded(item) { 84 bool isExpanded(item) {
84 return _expanded.contains(item); 85 return _expanded.contains(item);
85 } 86 }
86 87
87 void expand(item, 88 void expand(item,
88 {bool autoExpandSingleChildNodes: false, 89 {bool autoExpandSingleChildNodes: false,
89 bool autoExpandWholeTree: false}) { 90 bool autoExpandWholeTree: false}) {
90 if (_expanded.add(item)) _r.dirty(); 91 if (_expanded.add(item)) _r.dirty();
91 if (autoExpandWholeTree) { 92 if (autoExpandWholeTree) {
92 for (final child in _children(item)) { 93 Queue toDo = new Queue();
rmacnak 2017/07/06 00:10:20 Maybe add a note here that the tree is potentially
cbernaschina 2017/07/06 00:33:46 Done.
93 expand(child, autoExpandWholeTree: true); 94 toDo.addAll(_children(item));
95 while (toDo.isNotEmpty) {
96 final item = toDo.removeFirst();
97 if (_expanded.add(item)) _r.dirty();
98 toDo.addAll(_children(item));
94 } 99 }
95 } else if (autoExpandSingleChildNodes) { 100 } else if (autoExpandSingleChildNodes) {
96 var children = _children(item); 101 var children = _children(item);
97 while (children.length == 1) { 102 while (children.length == 1) {
98 _expanded.add(children.first); 103 _expanded.add(children.first);
99 children = _children(children.first); 104 children = _children(children.first);
100 } 105 }
101 } 106 }
102 } 107 }
103 108
104 void collapse(item, 109 void collapse(item,
105 {bool autoCollapseSingleChildNodes: false, 110 {bool autoCollapseSingleChildNodes: false,
106 bool autoCollapseWholeTree: false}) { 111 bool autoCollapseWholeTree: false}) {
107 if (_expanded.remove(item)) _r.dirty(); 112 if (_expanded.remove(item)) _r.dirty();
108 if (autoCollapseWholeTree) { 113 if (autoCollapseWholeTree) {
109 for (final child in _children(item)) { 114 Queue toDo = new Queue();
110 collapse(child, autoCollapseWholeTree: true); 115 toDo.addAll(_children(item));
116 while (toDo.isNotEmpty) {
117 final item = toDo.removeFirst();
118 if (_expanded.remove(item)) _r.dirty();
119 toDo.addAll(_children(item));
111 } 120 }
112 } else if (autoCollapseSingleChildNodes) { 121 } else if (autoCollapseSingleChildNodes) {
113 var children = _children(item); 122 var children = _children(item);
114 while (children.length == 1) { 123 while (children.length == 1) {
115 _expanded.remove(children.first); 124 _expanded.remove(children.first);
116 children = _children(children.first); 125 children = _children(children.first);
117 } 126 }
118 } 127 }
119 } 128 }
120 129
121 @override 130 @override
122 attached() { 131 attached() {
123 super.attached(); 132 super.attached();
124 _r.enable(); 133 _r.enable();
125 } 134 }
126 135
127 @override 136 @override
128 detached() { 137 detached() {
129 super.detached(); 138 super.detached();
130 _r.disable(notify: true); 139 _r.disable(notify: true);
131 children = const []; 140 children = const [];
132 } 141 }
133 142
134 VirtualCollectionElement _collection; 143 VirtualCollectionElement _collection;
135 144
136 void render() { 145 void render() {
137 if (children.length == 0) { 146 if (children.length == 0) {
138 children = [_collection]; 147 children = [_collection];
139 } 148 }
140 Iterable _toList(item) { 149
141 if (isExpanded(item)) { 150 final items = [];
142 Iterable children = _children(item); 151 final depths = new List.filled(_items.length, 0, growable: true);
143 if (children.isNotEmpty) { 152
144 return [item]..addAll(children.expand(_toList)); 153 {
154 final toDo = new Queue();
155
156 toDo.addAll(_items);
157 while (toDo.isNotEmpty) {
158 final item = toDo.removeFirst();
159
160 items.add(item);
161 if (isExpanded(item)) {
162 final children = _children(item);
163 children
164 .toList(growable: false)
165 .reversed
166 .forEach((c) => toDo.addFirst(c));
167 final depth = depths[items.length - 1];
168 depths.insertAll(
169 items.length, new List.filled(children.length, depth + 1));
145 } 170 }
146 } 171 }
147 return [item];
148 } 172 }
149 173
150 _collection.items = _items.expand(_toList); 174 _depths = depths;
151 var depth = 0; 175 _collection.items = items;
152 Iterable _toDepth(item) {
153 if (isExpanded(item)) {
154 Iterable children = _children(item);
155 if (children.isNotEmpty) {
156 depth++;
157 return children.expand(_toDepth).toList()..insert(0, --depth);
158 }
159 }
160 return [depth];
161 }
162
163 _depths = _items.expand(_toDepth).toList();
164 } 176 }
165 } 177 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698