Wrap dart:convert to track utf8 decode failures (#26650)
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart
index 9814318..9f9833f 100644
--- a/packages/flutter_tools/lib/src/android/android_device.dart
+++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:meta/meta.dart';
@@ -18,6 +17,7 @@
import '../base/process.dart';
import '../base/process_manager.dart';
import '../build_info.dart';
+import '../convert.dart';
import '../device.dart';
import '../globals.dart';
import '../project.dart';
@@ -681,7 +681,9 @@
_timeOrigin = null;
runCommand(device.adbCommandForDevice(args)).then<void>((Process process) {
_process = process;
- const Utf8Decoder decoder = Utf8Decoder(allowMalformed: true);
+ // We expect logcat streams to occasionally contain invalid utf-8,
+ // see: https://github.com/flutter/flutter/pull/8864.
+ const Utf8Decoder decoder = Utf8Decoder(reportErrors: false);
_process.stdout.transform<String>(decoder).transform<String>(const LineSplitter()).listen(_onLine);
_process.stderr.transform<String>(decoder).transform<String>(const LineSplitter()).listen(_onLine);
_process.exitCode.whenComplete(() {
diff --git a/packages/flutter_tools/lib/src/android/android_sdk.dart b/packages/flutter_tools/lib/src/android/android_sdk.dart
index 39f90f5..f97cc5b 100644
--- a/packages/flutter_tools/lib/src/android/android_sdk.dart
+++ b/packages/flutter_tools/lib/src/android/android_sdk.dart
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:convert';
-
import 'package:meta/meta.dart';
import '../base/common.dart';
@@ -15,6 +13,7 @@
import '../base/process.dart';
import '../base/process_manager.dart';
import '../base/version.dart';
+import '../convert.dart';
import '../globals.dart';
import 'android_studio.dart' as android_studio;
diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart
index dfbc083..00431f0 100644
--- a/packages/flutter_tools/lib/src/android/android_workflow.dart
+++ b/packages/flutter_tools/lib/src/android/android_workflow.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import '../base/common.dart';
import '../base/context.dart';
@@ -14,6 +13,7 @@
import '../base/user_messages.dart';
import '../base/utils.dart';
import '../base/version.dart';
+import '../convert.dart';
import '../doctor.dart';
import '../globals.dart';
import 'android_sdk.dart';
@@ -256,13 +256,15 @@
environment: androidSdk.sdkManagerEnv,
);
process.stdin.write('n\n');
+ // We expect logcat streams to occasionally contain invalid utf-8,
+ // see: https://github.com/flutter/flutter/pull/8864.
final Future<void> output = process.stdout
- .transform<String>(const Utf8Decoder(allowMalformed: true))
+ .transform<String>(const Utf8Decoder(reportErrors: false))
.transform<String>(const LineSplitter())
.listen(_handleLine)
.asFuture<void>(null);
final Future<void> errors = process.stderr
- .transform<String>(const Utf8Decoder(allowMalformed: true))
+ .transform<String>(const Utf8Decoder(reportErrors: false))
.transform<String>(const LineSplitter())
.listen(_handleLine)
.asFuture<void>(null);
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart
index a13d137..9cc182d 100644
--- a/packages/flutter_tools/lib/src/android/gradle.dart
+++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:archive/archive.dart';
import 'package:meta/meta.dart';
@@ -20,6 +19,7 @@
import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart';
+import '../convert.dart';
import '../flutter_manifest.dart';
import '../globals.dart';
import '../project.dart';
diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
index c5716af..d97d81b 100644
--- a/packages/flutter_tools/lib/src/asset.dart
+++ b/packages/flutter_tools/lib/src/asset.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:yaml/yaml.dart';
@@ -13,6 +12,7 @@
import 'base/utils.dart';
import 'build_info.dart';
import 'cache.dart';
+import 'convert.dart';
import 'dart/package_map.dart';
import 'devfs.dart';
import 'flutter_manifest.dart';
diff --git a/packages/flutter_tools/lib/src/base/config.dart b/packages/flutter_tools/lib/src/base/config.dart
index 7703326..54c440c 100644
--- a/packages/flutter_tools/lib/src/base/config.dart
+++ b/packages/flutter_tools/lib/src/base/config.dart
@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:convert';
-
+import '../convert.dart';
import 'context.dart';
import 'file_system.dart';
import 'platform.dart';
diff --git a/packages/flutter_tools/lib/src/base/fingerprint.dart b/packages/flutter_tools/lib/src/base/fingerprint.dart
index b898ed7..79a8333 100644
--- a/packages/flutter_tools/lib/src/base/fingerprint.dart
+++ b/packages/flutter_tools/lib/src/base/fingerprint.dart
@@ -3,12 +3,12 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert' show json;
import 'package:crypto/crypto.dart' show md5;
import 'package:meta/meta.dart';
import 'package:quiver/core.dart' show hash2;
+import '../convert.dart' show json;
import '../globals.dart';
import '../version.dart';
import 'file_system.dart';
diff --git a/packages/flutter_tools/lib/src/base/process.dart b/packages/flutter_tools/lib/src/base/process.dart
index 8dca327..40e085e 100644
--- a/packages/flutter_tools/lib/src/base/process.dart
+++ b/packages/flutter_tools/lib/src/base/process.dart
@@ -3,8 +3,8 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
+import '../convert.dart';
import '../globals.dart';
import 'file_system.dart';
import 'io.dart';
diff --git a/packages/flutter_tools/lib/src/base/terminal.dart b/packages/flutter_tools/lib/src/base/terminal.dart
index 6f9d542..de7f012 100644
--- a/packages/flutter_tools/lib/src/base/terminal.dart
+++ b/packages/flutter_tools/lib/src/base/terminal.dart
@@ -3,8 +3,8 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert' show AsciiDecoder;
+import '../convert.dart';
import '../globals.dart';
import 'context.dart';
import 'io.dart' as io;
diff --git a/packages/flutter_tools/lib/src/base/utils.dart b/packages/flutter_tools/lib/src/base/utils.dart
index ae94dd6..2062631 100644
--- a/packages/flutter_tools/lib/src/base/utils.dart
+++ b/packages/flutter_tools/lib/src/base/utils.dart
@@ -3,12 +3,12 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'dart:math' show Random, max;
import 'package:crypto/crypto.dart';
import 'package:intl/intl.dart';
+import '../convert.dart';
import '../globals.dart';
import 'context.dart';
import 'file_system.dart';
diff --git a/packages/flutter_tools/lib/src/build_runner/build_runner.dart b/packages/flutter_tools/lib/src/build_runner/build_runner.dart
index 7035ddd..3c062cf 100644
--- a/packages/flutter_tools/lib/src/build_runner/build_runner.dart
+++ b/packages/flutter_tools/lib/src/build_runner/build_runner.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:meta/meta.dart';
@@ -14,6 +13,7 @@
import '../base/platform.dart';
import '../base/process_manager.dart';
import '../cache.dart';
+import '../convert.dart';
import '../dart/package_map.dart';
import '../globals.dart';
import '../project.dart';
diff --git a/packages/flutter_tools/lib/src/commands/config.dart b/packages/flutter_tools/lib/src/commands/config.dart
index 2c5bd94..3b2b526 100644
--- a/packages/flutter_tools/lib/src/commands/config.dart
+++ b/packages/flutter_tools/lib/src/commands/config.dart
@@ -3,10 +3,10 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import '../android/android_sdk.dart';
import '../android/android_studio.dart';
+import '../convert.dart';
import '../globals.dart';
import '../runner/flutter_command.dart';
import '../usage.dart';
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index e20bb5f..ec6f616 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:linter/src/rules/pub/package_names.dart' as package_names; // ignore: implementation_imports
import 'package:linter/src/utils.dart' as linter_utils; // ignore: implementation_imports
@@ -18,6 +17,7 @@
import '../base/os.dart';
import '../base/utils.dart';
import '../cache.dart';
+import '../convert.dart';
import '../dart/pub.dart';
import '../doctor.dart';
import '../globals.dart';
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart
index 79d3071..de597b3 100644
--- a/packages/flutter_tools/lib/src/commands/daemon.dart
+++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:meta/meta.dart';
@@ -17,6 +16,7 @@
import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart';
+import '../convert.dart';
import '../device.dart';
import '../emulator.dart';
import '../fuchsia/fuchsia_device.dart';
diff --git a/packages/flutter_tools/lib/src/commands/screenshot.dart b/packages/flutter_tools/lib/src/commands/screenshot.dart
index 20a2d1f..449a1b8 100644
--- a/packages/flutter_tools/lib/src/commands/screenshot.dart
+++ b/packages/flutter_tools/lib/src/commands/screenshot.dart
@@ -3,11 +3,11 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/utils.dart';
+import '../convert.dart';
import '../device.dart';
import '../globals.dart';
import '../runner/flutter_command.dart';
diff --git a/packages/flutter_tools/lib/src/commands/trace.dart b/packages/flutter_tools/lib/src/commands/trace.dart
index 7956964..96ef949 100644
--- a/packages/flutter_tools/lib/src/commands/trace.dart
+++ b/packages/flutter_tools/lib/src/commands/trace.dart
@@ -3,12 +3,12 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/utils.dart';
import '../cache.dart';
+import '../convert.dart';
import '../globals.dart';
import '../runner/flutter_command.dart';
import '../tracing.dart';
diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
index 8439c98..29fa0c6 100644
--- a/packages/flutter_tools/lib/src/compile.dart
+++ b/packages/flutter_tools/lib/src/compile.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:meta/meta.dart';
import 'package:usage/uuid/uuid.dart';
@@ -17,6 +16,7 @@
import 'base/platform.dart';
import 'base/process_manager.dart';
import 'base/terminal.dart';
+import 'convert.dart';
import 'dart/package_map.dart';
import 'globals.dart';
diff --git a/packages/flutter_tools/lib/src/convert.dart b/packages/flutter_tools/lib/src/convert.dart
new file mode 100644
index 0000000..83c8d7d
--- /dev/null
+++ b/packages/flutter_tools/lib/src/convert.dart
@@ -0,0 +1,49 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Hide the original utf8 [Codec] so that we can export our own implementation
+// which adds additional error handling.
+import 'dart:convert' hide utf8;
+import 'dart:convert' as cnv show utf8, Utf8Decoder;
+
+import 'base/common.dart';
+export 'dart:convert' hide utf8, Utf8Codec, Utf8Decoder;
+
+/// A [Codec] which reports malformed bytes when decoding.
+// Created to solve https://github.com/flutter/flutter/issues/15646.
+class Utf8Codec extends Encoding {
+ const Utf8Codec();
+
+ @override
+ Converter<List<int>, String> get decoder => const Utf8Decoder();
+
+ @override
+ Converter<String, List<int>> get encoder => cnv.utf8.encoder;
+
+ @override
+ String get name => cnv.utf8.name;
+}
+
+Encoding get utf8 => const Utf8Codec();
+
+class Utf8Decoder extends cnv.Utf8Decoder {
+ const Utf8Decoder({this.reportErrors = true}) : super(allowMalformed: true);
+
+ final bool reportErrors;
+
+ @override
+ String convert(List<int> codeUnits, [int start = 0, int end]) {
+ final String result = super.convert(codeUnits, start, end);
+ // Finding a unicode replacement character indicates that the input
+ // was malformed.
+ if (reportErrors && result.contains('\u{FFFD}')) {
+ throwToolExit(
+ 'Bad UTF-8 encoding found while decoding string: $result. '
+ 'The Flutter team would greatly appreciate if you could file a bug or leave a'
+ 'comment on the issue https://github.com/flutter/flutter/issues/15646.\n'
+ 'The source bytes were:\n$codeUnits\n\n');
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/packages/flutter_tools/lib/src/dart/analysis.dart b/packages/flutter_tools/lib/src/dart/analysis.dart
index a80aff0..df4b2d1 100644
--- a/packages/flutter_tools/lib/src/dart/analysis.dart
+++ b/packages/flutter_tools/lib/src/dart/analysis.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'dart:math' as math;
import '../base/file_system.dart' hide IOSink;
@@ -13,6 +12,7 @@
import '../base/process_manager.dart';
import '../base/terminal.dart';
import '../base/utils.dart';
+import '../convert.dart';
import '../globals.dart';
class AnalysisServer {
diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
index 07adbba..75ebec8 100644
--- a/packages/flutter_tools/lib/src/devfs.dart
+++ b/packages/flutter_tools/lib/src/devfs.dart
@@ -3,8 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert' show base64, utf8;
-
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
import 'package:meta/meta.dart';
@@ -15,6 +13,7 @@
import 'build_info.dart';
import 'bundle.dart';
import 'compile.dart';
+import 'convert.dart' show base64, utf8;
import 'dart/package_map.dart';
import 'globals.dart';
import 'vmservice.dart';
diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart
index bb731d8..50ff01e 100644
--- a/packages/flutter_tools/lib/src/flutter_manifest.dart
+++ b/packages/flutter_tools/lib/src/flutter_manifest.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert' as convert;
import 'package:json_schema/json_schema.dart';
import 'package:meta/meta.dart';
@@ -12,6 +11,7 @@
import 'base/file_system.dart';
import 'base/utils.dart';
import 'cache.dart';
+import 'convert.dart' as convert;
import 'globals.dart';
final RegExp _versionPattern = RegExp(r'^(\d+)(\.(\d+)(\.(\d+))?)?(\+(\d+))?$');
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart
index 330835f..ed090c0 100644
--- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart
+++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart
@@ -3,13 +3,13 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/process.dart';
import '../base/process_manager.dart';
+import '../convert.dart';
import '../globals.dart';
/// The [FuchsiaSdk] instance.
diff --git a/packages/flutter_tools/lib/src/intellij/intellij.dart b/packages/flutter_tools/lib/src/intellij/intellij.dart
index 46278ba..7bed197 100644
--- a/packages/flutter_tools/lib/src/intellij/intellij.dart
+++ b/packages/flutter_tools/lib/src/intellij/intellij.dart
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:convert';
-
import 'package:archive/archive.dart';
import '../base/file_system.dart';
import '../base/version.dart';
+import '../convert.dart';
import '../doctor.dart';
class IntelliJPlugins {
diff --git a/packages/flutter_tools/lib/src/ios/code_signing.dart b/packages/flutter_tools/lib/src/ios/code_signing.dart
index f878887..7778654 100644
--- a/packages/flutter_tools/lib/src/ios/code_signing.dart
+++ b/packages/flutter_tools/lib/src/ios/code_signing.dart
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert' show utf8;
import 'package:quiver/strings.dart';
@@ -11,6 +10,7 @@
import '../base/io.dart';
import '../base/process.dart';
import '../base/terminal.dart';
+import '../convert.dart' show utf8;
import '../globals.dart';
/// User message when no development certificates are found in the keychain.
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index b372d6a..d250ea0 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:meta/meta.dart';
@@ -15,6 +14,7 @@
import '../base/process.dart';
import '../base/process_manager.dart';
import '../build_info.dart';
+import '../convert.dart';
import '../device.dart';
import '../globals.dart';
import '../protocol_discovery.dart';
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index bcb24be..dd87a5e 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert' show json;
import 'package:meta/meta.dart';
@@ -20,6 +19,7 @@
import '../base/process_manager.dart';
import '../base/utils.dart';
import '../build_info.dart';
+import '../convert.dart';
import '../globals.dart';
import '../plugins.dart';
import '../project.dart';
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart
index 69c8a1c..2ac62f8 100644
--- a/packages/flutter_tools/lib/src/ios/simulators.dart
+++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'dart:math' as math;
import '../application_package.dart';
@@ -17,6 +16,7 @@
import '../base/utils.dart';
import '../build_info.dart';
import '../bundle.dart' as bundle;
+import '../convert.dart';
import '../device.dart';
import '../globals.dart';
import '../protocol_discovery.dart';
diff --git a/packages/flutter_tools/lib/src/macos/macos_device.dart b/packages/flutter_tools/lib/src/macos/macos_device.dart
index 529226f..7ba605b 100644
--- a/packages/flutter_tools/lib/src/macos/macos_device.dart
+++ b/packages/flutter_tools/lib/src/macos/macos_device.dart
@@ -2,14 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:convert';
-
import '../application_package.dart';
import '../base/io.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../base/process_manager.dart';
import '../build_info.dart';
+import '../convert.dart';
import '../device.dart';
import '../globals.dart';
import '../macos/application_package.dart';
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart
index c5f1039..df9627e 100644
--- a/packages/flutter_tools/lib/src/run_hot.dart
+++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:json_rpc_2/error_code.dart' as rpc_error_code;
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
@@ -17,6 +16,7 @@
import 'base/utils.dart';
import 'build_info.dart';
import 'compile.dart';
+import 'convert.dart';
import 'dart/dependencies.dart';
import 'dart/pub.dart';
import 'devfs.dart';
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
index 68cc71e..04d654e 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
@@ -27,6 +26,7 @@
import '../base/user_messages.dart';
import '../base/utils.dart';
import '../cache.dart';
+import '../convert.dart';
import '../dart/package_map.dart';
import '../device.dart';
import '../globals.dart';
diff --git a/packages/flutter_tools/lib/src/services.dart b/packages/flutter_tools/lib/src/services.dart
index 934f05e..fee5383 100644
--- a/packages/flutter_tools/lib/src/services.dart
+++ b/packages/flutter_tools/lib/src/services.dart
@@ -3,12 +3,12 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:yaml/yaml.dart';
import 'android/android_sdk.dart';
import 'base/file_system.dart';
+import 'convert.dart';
import 'dart/package_map.dart';
import 'globals.dart';
diff --git a/packages/flutter_tools/lib/src/test/event_printer.dart b/packages/flutter_tools/lib/src/test/event_printer.dart
index ab2648f..e672f20 100644
--- a/packages/flutter_tools/lib/src/test/event_printer.dart
+++ b/packages/flutter_tools/lib/src/test/event_printer.dart
@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:convert' show json;
-
import '../base/io.dart' show stdout;
+import '../convert.dart';
import 'watcher.dart';
/// Prints JSON events when running a test in --machine mode.
diff --git a/packages/flutter_tools/lib/src/test/flutter_platform.dart b/packages/flutter_tools/lib/src/test/flutter_platform.dart
index 5886f03..70bbf52 100644
--- a/packages/flutter_tools/lib/src/test/flutter_platform.dart
+++ b/packages/flutter_tools/lib/src/test/flutter_platform.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:meta/meta.dart';
import 'package:stream_channel/stream_channel.dart';
@@ -26,6 +25,7 @@
import '../build_info.dart';
import '../bundle.dart';
import '../compile.dart';
+import '../convert.dart';
import '../dart/package_map.dart';
import '../globals.dart';
import '../vmservice.dart';
@@ -144,7 +144,7 @@
final StringBuffer buffer = StringBuffer();
buffer.write('''
import 'dart:async';
-import 'dart:convert';
+import 'dart:convert'; // ignore: dart_convert_import
import 'dart:io'; // ignore: dart_io_import
import 'dart:isolate';
diff --git a/packages/flutter_tools/lib/src/tester/flutter_tester.dart b/packages/flutter_tools/lib/src/tester/flutter_tester.dart
index f3e2092..de29600 100644
--- a/packages/flutter_tools/lib/src/tester/flutter_tester.dart
+++ b/packages/flutter_tools/lib/src/tester/flutter_tester.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:meta/meta.dart';
@@ -15,6 +14,7 @@
import '../base/process_manager.dart';
import '../build_info.dart';
import '../bundle.dart' as bundle;
+import '../convert.dart';
import '../dart/package_map.dart';
import '../device.dart';
import '../globals.dart';
diff --git a/packages/flutter_tools/lib/src/version.dart b/packages/flutter_tools/lib/src/version.dart
index 9e3cb56..29dbc5e 100644
--- a/packages/flutter_tools/lib/src/version.dart
+++ b/packages/flutter_tools/lib/src/version.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:meta/meta.dart';
@@ -15,6 +14,7 @@
import 'base/process_manager.dart';
import 'base/time.dart';
import 'cache.dart';
+import 'convert.dart';
import 'globals.dart';
class FlutterVersion {
diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart
index 7a72740..c733b52 100644
--- a/packages/flutter_tools/lib/src/vmservice.dart
+++ b/packages/flutter_tools/lib/src/vmservice.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert' show base64;
import 'dart:math' as math;
import 'package:file/file.dart';
@@ -19,6 +18,7 @@
import 'base/file_system.dart';
import 'base/io.dart' as io;
import 'base/utils.dart';
+import 'convert.dart' show base64;
import 'globals.dart';
import 'vmservice_record_replay.dart';
diff --git a/packages/flutter_tools/lib/src/vmservice_record_replay.dart b/packages/flutter_tools/lib/src/vmservice_record_replay.dart
index 4749b58..0061fd4 100644
--- a/packages/flutter_tools/lib/src/vmservice_record_replay.dart
+++ b/packages/flutter_tools/lib/src/vmservice_record_replay.dart
@@ -3,13 +3,13 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:convert';
import 'package:file/file.dart';
import 'package:stream_channel/stream_channel.dart';
import 'base/io.dart';
import 'base/process.dart';
+import 'convert.dart';
import 'globals.dart';
const String _kManifest = 'MANIFEST.txt';
diff --git a/packages/flutter_tools/lib/src/vscode/vscode.dart b/packages/flutter_tools/lib/src/vscode/vscode.dart
index 00dda29..c9503fd 100644
--- a/packages/flutter_tools/lib/src/vscode/vscode.dart
+++ b/packages/flutter_tools/lib/src/vscode/vscode.dart
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:convert';
-
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/platform.dart';
import '../base/version.dart';
+import '../convert.dart';
import '../doctor.dart';
// Include VS Code insiders (useful for debugging).
diff --git a/packages/flutter_tools/test/forbidden_imports_test.dart b/packages/flutter_tools/test/forbidden_imports_test.dart
index cf3b387..06b1fc6 100644
--- a/packages/flutter_tools/test/forbidden_imports_test.dart
+++ b/packages/flutter_tools/test/forbidden_imports_test.dart
@@ -47,6 +47,28 @@
}
}
});
+
+ test('no unauthorized imports of dart:convert', () {
+ final String whitelistedPath = fs.path.join(flutterTools, 'lib', 'src', 'convert.dart');
+ bool _isNotWhitelisted(FileSystemEntity entity) => entity.path != whitelistedPath;
+
+ for (String dirName in <String>['lib']) {
+ final Iterable<File> files = fs.directory(fs.path.join(flutterTools, dirName))
+ .listSync(recursive: true)
+ .where(_isDartFile)
+ .where(_isNotWhitelisted)
+ .map(_asFile);
+ for (File file in files) {
+ for (String line in file.readAsLinesSync()) {
+ if (line.startsWith(RegExp(r'import.*dart:convert')) &&
+ !line.contains('ignore: dart_convert_import')) {
+ final String relativePath = fs.path.relative(file.path, from:flutterTools);
+ fail("$relativePath imports 'dart:convert'; import 'lib/src/convert.dart' instead");
+ }
+ }
+ }
+ }
+ });
}
bool _isDartFile(FileSystemEntity entity) => entity is File && entity.path.endsWith('.dart');