Be more resilient to bad data from VM (#18132)
Fixes https://github.com/flutter/flutter/issues/14517
Or at least, fixes the crash part of that.
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart
index dcb16ae..6c98710 100644
--- a/packages/flutter_tools/lib/src/run_hot.dart
+++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -412,7 +412,24 @@
/// Prints errors if [printErrors] is [true].
static bool validateReloadReport(Map<String, dynamic> reloadReport,
{ bool printErrors: true }) {
- if (reloadReport['type'] != 'ReloadReport') {
+ if (reloadReport == null) {
+ if (printErrors)
+ printError('Hot reload did not receive reload report.');
+ return false;
+ }
+ if (!(reloadReport['type'] == 'ReloadReport' &&
+ (reloadReport['success'] == true ||
+ (reloadReport['success'] == false &&
+ (reloadReport['details'] is Map<String, dynamic> &&
+ reloadReport['details']['notices'] is List<dynamic> &&
+ reloadReport['details']['notices'].isNotEmpty &&
+ reloadReport['details']['notices'].every(
+ (dynamic item) => item is Map<String, dynamic> && item['message'] is String
+ )
+ )
+ )
+ )
+ )) {
if (printErrors)
printError('Hot reload received invalid response: $reloadReport');
return false;
diff --git a/packages/flutter_tools/test/hot_test.dart b/packages/flutter_tools/test/hot_test.dart
index a09d174..73f7fd8 100644
--- a/packages/flutter_tools/test/hot_test.dart
+++ b/packages/flutter_tools/test/hot_test.dart
@@ -11,9 +11,76 @@
group('validateReloadReport', () {
testUsingContext('invalid', () async {
expect(HotRunner.validateReloadReport(<String, dynamic>{}), false);
- expect(HotRunner.validateReloadReport(
- <String, dynamic>{'type': 'ReloadReport', 'success': true, 'details': <String, dynamic>{}}),
- true);
+ expect(HotRunner.validateReloadReport(<String, dynamic>{
+ 'type': 'ReloadReport',
+ 'success': false,
+ 'details': <String, dynamic>{},
+ }), false);
+ expect(HotRunner.validateReloadReport(<String, dynamic>{
+ 'type': 'ReloadReport',
+ 'success': false,
+ 'details': <String, dynamic>{
+ 'notices': <Map<String, dynamic>>[
+ ],
+ },
+ }), false);
+ expect(HotRunner.validateReloadReport(<String, dynamic>{
+ 'type': 'ReloadReport',
+ 'success': false,
+ 'details': <String, dynamic>{
+ 'notices': <String, dynamic>{
+ 'message': 'error',
+ },
+ },
+ }), false);
+ expect(HotRunner.validateReloadReport(<String, dynamic>{
+ 'type': 'ReloadReport',
+ 'success': false,
+ 'details': <String, dynamic>{
+ 'notices': <Map<String, dynamic>>[],
+ },
+ }), false);
+ expect(HotRunner.validateReloadReport(<String, dynamic>{
+ 'type': 'ReloadReport',
+ 'success': false,
+ 'details': <String, dynamic>{
+ 'notices': <Map<String, dynamic>>[
+ <String, dynamic>{ 'message': false, }
+ ],
+ },
+ }), false);
+ expect(HotRunner.validateReloadReport(<String, dynamic>{
+ 'type': 'ReloadReport',
+ 'success': false,
+ 'details': <String, dynamic>{
+ 'notices': <Map<String, dynamic>>[
+ <String, dynamic>{ 'message': <String>['error'], },
+ ],
+ },
+ }), false);
+ expect(HotRunner.validateReloadReport(<String, dynamic>{
+ 'type': 'ReloadReport',
+ 'success': false,
+ 'details': <String, dynamic>{
+ 'notices': <Map<String, dynamic>>[
+ <String, dynamic>{ 'message': 'error', },
+ <String, dynamic>{ 'message': <String>['error'], },
+ ],
+ },
+ }), false);
+ expect(HotRunner.validateReloadReport(<String, dynamic>{
+ 'type': 'ReloadReport',
+ 'success': false,
+ 'details': <String, dynamic>{
+ 'notices': <Map<String, dynamic>>[
+ <String, dynamic>{ 'message': 'error', },
+ ],
+ },
+ }), false);
+ expect(HotRunner.validateReloadReport(<String, dynamic>{
+ 'type': 'ReloadReport',
+ 'success': true,
+ }), true);
});
});
}