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

Commit b86bc24

Browse files
authored
[web] Fix exception when using a keyboard (#24150)
1 parent 08f39f7 commit b86bc24

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

lib/web_ui/lib/src/engine/platform_dispatcher.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,15 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
194194
/// Engine code should use this method instead of the callback directly.
195195
/// Otherwise zones won't work properly.
196196
void invokeOnKeyData(ui.KeyData data, _KeyDataResponseCallback callback) {
197-
invoke(
198-
() { callback(onKeyData == null ? false : onKeyData!(data)); },
199-
_onKeyDataZone,
200-
);
197+
final ui.KeyDataCallback? onKeyData = _onKeyData;
198+
if (onKeyData != null) {
199+
invoke(
200+
() => callback(onKeyData(data)),
201+
_onKeyDataZone,
202+
);
203+
} else {
204+
callback(false);
205+
}
201206
}
202207

203208
/// A callback that is invoked to report the [FrameTiming] of recently

lib/web_ui/test/engine/window_test.dart

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import 'package:test/test.dart';
1313
import 'package:ui/ui.dart' as ui;
1414
import 'package:ui/src/engine.dart';
1515

16+
const int kPhysicalKeyA = 0x00070004;
17+
const int kLogicalKeyA = 0x00000000061;
18+
1619
void main() {
1720
internalBootstrapBrowserTest(() => testMain);
1821
}
@@ -146,6 +149,52 @@ void testMain() {
146149
EnginePlatformDispatcher.instance.invokeOnPointerDataPacket(null);
147150
});
148151

152+
test('invokeOnKeyData returns normally when onKeyData is null', () {
153+
final ui.KeyData keyData = ui.KeyData(
154+
timeStamp: Duration(milliseconds: 1),
155+
type: ui.KeyEventType.repeat,
156+
physical: kPhysicalKeyA,
157+
logical: kLogicalKeyA,
158+
character: 'a',
159+
synthesized: true,
160+
);
161+
expect(() {
162+
EnginePlatformDispatcher.instance.invokeOnKeyData(keyData, (bool result) {
163+
expect(result, isFalse);
164+
});
165+
}, returnsNormally);
166+
});
167+
168+
test('onKeyData preserves the zone', () {
169+
final Zone innerZone = Zone.current.fork();
170+
171+
innerZone.runGuarded(() {
172+
final ui.KeyDataCallback onKeyData = (_) {
173+
expect(Zone.current, innerZone);
174+
return false;
175+
};
176+
window.onKeyData = onKeyData;
177+
178+
// Test that the getter returns the exact same onKeyData, e.g. it doesn't
179+
// wrap it.
180+
expect(window.onKeyData, same(onKeyData));
181+
});
182+
183+
final ui.KeyData keyData = ui.KeyData(
184+
timeStamp: Duration(milliseconds: 1),
185+
type: ui.KeyEventType.repeat,
186+
physical: kPhysicalKeyA,
187+
logical: kLogicalKeyA,
188+
character: 'a',
189+
synthesized: true,
190+
);
191+
EnginePlatformDispatcher.instance.invokeOnKeyData(keyData, (bool result) {
192+
expect(result, isFalse);
193+
});
194+
195+
window.onKeyData = null;
196+
});
197+
149198
test('onSemanticsEnabledChanged preserves the zone', () {
150199
final Zone innerZone = Zone.current.fork();
151200

0 commit comments

Comments
 (0)