Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 578edfc

Browse files
authored
Catch errors thrown while handling pointer events (#119577)
1 parent bc8927c commit 578edfc

File tree

2 files changed

+52
-13
lines changed

2 files changed

+52
-13
lines changed

packages/flutter/lib/src/gestures/binding.dart

+12-3
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,18 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
287287
void _handlePointerDataPacket(ui.PointerDataPacket packet) {
288288
// We convert pointer data to logical pixels so that e.g. the touch slop can be
289289
// defined in a device-independent manner.
290-
_pendingPointerEvents.addAll(PointerEventConverter.expand(packet.data, window.devicePixelRatio));
291-
if (!locked) {
292-
_flushPointerEventQueue();
290+
try {
291+
_pendingPointerEvents.addAll(PointerEventConverter.expand(packet.data, window.devicePixelRatio));
292+
if (!locked) {
293+
_flushPointerEventQueue();
294+
}
295+
} catch (error, stack) {
296+
FlutterError.reportError(FlutterErrorDetails(
297+
exception: error,
298+
stack: stack,
299+
library: 'gestures library',
300+
context: ErrorDescription('while handling a pointer data packet'),
301+
));
293302
}
294303
}
295304

packages/flutter/test/gestures/gesture_binding_test.dart

+40-10
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,20 @@ class TestGestureFlutterBinding extends BindingBase with GestureBinding, Schedul
3535
return _instance!;
3636
}
3737

38-
HandleEventCallback? callback;
38+
HandleEventCallback? onHandlePointerEvent;
39+
40+
@override
41+
void handlePointerEvent(PointerEvent event) {
42+
onHandlePointerEvent?.call(event);
43+
super.handlePointerEvent(event);
44+
}
45+
46+
HandleEventCallback? onHandleEvent;
3947

4048
@override
4149
void handleEvent(PointerEvent event, HitTestEntry entry) {
4250
super.handleEvent(event, entry);
43-
if (callback != null) {
44-
callback?.call(event);
45-
}
51+
onHandleEvent?.call(event);
4652
}
4753
}
4854

@@ -58,7 +64,7 @@ void main() {
5864
);
5965

6066
final List<PointerEvent> events = <PointerEvent>[];
61-
binding.callback = events.add;
67+
binding.onHandleEvent = events.add;
6268

6369
GestureBinding.instance.platformDispatcher.onPointerDataPacket?.call(packet);
6470
expect(events.length, 2);
@@ -76,7 +82,7 @@ void main() {
7682
);
7783

7884
final List<PointerEvent> events = <PointerEvent>[];
79-
binding.callback = events.add;
85+
binding.onHandleEvent = events.add;
8086

8187
GestureBinding.instance.platformDispatcher.onPointerDataPacket?.call(packet);
8288
expect(events.length, 3);
@@ -101,7 +107,7 @@ void main() {
101107
GestureBinding.instance.pointerRouter.addGlobalRoute(pointerRouterEvents.add);
102108

103109
final List<PointerEvent> events = <PointerEvent>[];
104-
binding.callback = events.add;
110+
binding.onHandleEvent = events.add;
105111

106112
GestureBinding.instance.platformDispatcher.onPointerDataPacket?.call(packet);
107113
expect(events.length, 3);
@@ -126,7 +132,7 @@ void main() {
126132
);
127133

128134
final List<PointerEvent> events = <PointerEvent>[];
129-
binding.callback = events.add;
135+
binding.onHandleEvent = events.add;
130136

131137
GestureBinding.instance.platformDispatcher.onPointerDataPacket?.call(packet);
132138
expect(events.length, 2);
@@ -143,7 +149,7 @@ void main() {
143149
);
144150

145151
final List<PointerEvent> events = <PointerEvent>[];
146-
binding.callback = (PointerEvent event) {
152+
binding.onHandleEvent = (PointerEvent event) {
147153
events.add(event);
148154
if (event is PointerDownEvent) {
149155
binding.cancelPointer(event.pointer);
@@ -389,12 +395,36 @@ void main() {
389395
);
390396

391397
final List<PointerEvent> events = <PointerEvent>[];
392-
binding.callback = events.add;
398+
binding.onHandleEvent = events.add;
393399

394400
binding.platformDispatcher.onPointerDataPacket?.call(packet);
395401
expect(events.length, 3);
396402
expect(events[0], isA<PointerPanZoomStartEvent>());
397403
expect(events[1], isA<PointerPanZoomUpdateEvent>());
398404
expect(events[2], isA<PointerPanZoomEndEvent>());
399405
});
406+
407+
test('Error handling', () {
408+
const ui.PointerDataPacket packet = ui.PointerDataPacket(
409+
data: <ui.PointerData>[
410+
ui.PointerData(change: ui.PointerChange.down),
411+
ui.PointerData(change: ui.PointerChange.up),
412+
],
413+
);
414+
415+
final List<String> events = <String>[];
416+
binding.onHandlePointerEvent = (PointerEvent event) { throw Exception('zipzapzooey $event'); };
417+
FlutterError.onError = (FlutterErrorDetails details) { events.add(details.toString()); };
418+
try {
419+
GestureBinding.instance.platformDispatcher.onPointerDataPacket?.call(packet);
420+
expect(events.length, 1);
421+
expect(events[0], contains('while handling a pointer data\npacket')); // The default stringifying behavior uses 65 character wrapWidth.
422+
expect(events[0], contains('zipzapzooey'));
423+
expect(events[0], contains('PointerDownEvent'));
424+
expect(events[0], isNot(contains('PointerUpEvent'))); // Failure happens on the first message, remaining messages aren't processed.
425+
} finally {
426+
binding.onHandlePointerEvent = null;
427+
FlutterError.onError = FlutterError.presentError;
428+
}
429+
});
400430
}

0 commit comments

Comments
 (0)