Skip to content

Commit 04211b9

Browse files
authored
refactor: use breadth-first search in widget-filter (#2481)
1 parent 20a5bce commit 04211b9

File tree

2 files changed

+29
-11
lines changed

2 files changed

+29
-11
lines changed

flutter/lib/src/screenshot/widget_filter.dart

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class WidgetFilter {
1414
late WidgetFilterColorScheme _scheme;
1515
late double _pixelRatio;
1616
late Rect _bounds;
17+
late List<Element> _visitList;
1718
final _warnedWidgets = <int>{};
1819

1920
/// Used to test _obscureElementOrParent
@@ -34,11 +35,24 @@ class WidgetFilter {
3435
assert(colorScheme.background.isOpaque);
3536
assert(colorScheme.defaultMask.isOpaque);
3637
assert(colorScheme.defaultTextMask.isOpaque);
38+
39+
// clear the output list
3740
items.clear();
38-
if (context is Element) {
39-
_process(context);
40-
} else {
41-
context.visitChildElements(_process);
41+
42+
// Reset the list of elements we're going to process.
43+
// Then do a breadth-first tree traversal on all the widgets.
44+
// TODO benchmark performance compared to to DoubleLinkedQueue.
45+
_visitList = [];
46+
context.visitChildElements(_visitList.add);
47+
while (_visitList.isNotEmpty) {
48+
// Get a handle on the items we're supposed to process in this step.
49+
// Then _visitList (which is updated in _process()) with a new instance.
50+
final currentList = _visitList;
51+
_visitList = [];
52+
53+
for (final element in currentList) {
54+
_process(element);
55+
}
4256
}
4357
}
4458

@@ -66,7 +80,7 @@ class WidgetFilter {
6680
break;
6781
case SentryMaskingDecision.continueProcessing:
6882
// If this element should not be obscured, visit and check its children.
69-
element.visitChildElements(_process);
83+
element.visitChildElements(_visitList.add);
7084
break;
7185
}
7286
}

flutter/test/screenshot/widget_filter_test.dart

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,16 @@ void main() async {
8181
bounds: defaultBounds,
8282
colorScheme: colorScheme);
8383
expect(sut.items.length, 6);
84-
expect(boundsRect(sut.items[0]), '624x48');
85-
expect(boundsRect(sut.items[1]), '169x20');
86-
expect(boundsRect(sut.items[2]), '800x192');
87-
expect(boundsRect(sut.items[3]), '800x24');
88-
expect(boundsRect(sut.items[4]), '800x24');
89-
expect(boundsRect(sut.items[5]), '50x20');
84+
expect(
85+
sut.items.map(boundsRect),
86+
unorderedEquals([
87+
'624x48',
88+
'169x20',
89+
'800x192',
90+
'800x24',
91+
'800x24',
92+
'50x20',
93+
]));
9094
});
9195
});
9296

0 commit comments

Comments
 (0)