[releases] Handle privatecommand messages that pass no data #112590 (#114461)
Co-authored-by: Justin McCandless <jmccandless@google.com>
diff --git a/packages/flutter/lib/src/services/text_input.dart b/packages/flutter/lib/src/services/text_input.dart
index 4fee13b..e19757d 100644
--- a/packages/flutter/lib/src/services/text_input.dart
+++ b/packages/flutter/lib/src/services/text_input.dart
@@ -1820,7 +1820,9 @@
final Map<String, dynamic> firstArg = args[1] as Map<String, dynamic>;
_currentConnection!._client.performPrivateCommand(
firstArg['action'] as String,
- firstArg['data'] as Map<String, dynamic>,
+ firstArg['data'] == null
+ ? <String, dynamic>{}
+ : firstArg['data'] as Map<String, dynamic>,
);
break;
case 'TextInputClient.updateFloatingCursor':
diff --git a/packages/flutter/test/services/text_input_test.dart b/packages/flutter/test/services/text_input_test.dart
index 289f386..87c4204 100644
--- a/packages/flutter/test/services/text_input_test.dart
+++ b/packages/flutter/test/services/text_input_test.dart
@@ -506,6 +506,32 @@
expect(client.latestMethodCall, 'performPrivateCommand');
});
+ test('TextInputClient performPrivateCommand method is called with no data at all', () async {
+ // Assemble a TextInputConnection so we can verify its change in state.
+ final FakeTextInputClient client = FakeTextInputClient(TextEditingValue.empty);
+ const TextInputConfiguration configuration = TextInputConfiguration();
+ TextInput.attach(client, configuration);
+
+ expect(client.latestMethodCall, isEmpty);
+
+ // Send performPrivateCommand message.
+ final ByteData? messageBytes = const JSONMessageCodec().encodeMessage(<String, dynamic>{
+ 'args': <dynamic>[
+ 1,
+ jsonDecode('{"action": "actionCommand"}'), // No `data` parameter.
+ ],
+ 'method': 'TextInputClient.performPrivateCommand',
+ });
+ await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
+ 'flutter/textinput',
+ messageBytes,
+ (ByteData? _) {},
+ );
+
+ expect(client.latestMethodCall, 'performPrivateCommand');
+ expect(client.latestPrivateCommandData, <String, dynamic>{});
+ });
+
test('TextInputClient showAutocorrectionPromptRect method is called', () async {
// Assemble a TextInputConnection so we can verify its change in state.
final FakeTextInputClient client = FakeTextInputClient(TextEditingValue.empty);
@@ -704,6 +730,7 @@
FakeTextInputClient(this.currentTextEditingValue);
String latestMethodCall = '';
+ late Map<String, dynamic>? latestPrivateCommandData;
@override
TextEditingValue currentTextEditingValue;
@@ -717,8 +744,9 @@
}
@override
- void performPrivateCommand(String action, Map<String, dynamic> data) {
+ void performPrivateCommand(String action, Map<String, dynamic>? data) {
latestMethodCall = 'performPrivateCommand';
+ latestPrivateCommandData = data;
}
@override