diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart index 95b043f3f2d..e1d7c87a0c1 100644 --- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart @@ -22,7 +22,6 @@ import '../base/terminal.dart'; import '../base/utils.dart'; import '../build_info.dart'; import '../cache.dart'; -import '../convert.dart'; import '../dart/language_version.dart'; import '../dart/pub.dart'; import '../devfs.dart'; @@ -731,14 +730,13 @@ class _ResidentWebRunner extends ResidentWebRunner { _connectionResult = await webDevFS.connect(useDebugExtension); unawaited(_connectionResult.debugConnection.onDone.whenComplete(_cleanupAndExit)); - _stdOutSub = _vmService.onStdoutEvent.listen((vmservice.Event log) { - final String message = utf8.decode(base64.decode(log.bytes)); - globals.printStatus(message, newline: false); - }); - _stdErrSub = _vmService.onStderrEvent.listen((vmservice.Event log) { - final String message = utf8.decode(base64.decode(log.bytes)); - globals.printStatus(message, newline: false); - }); + void onLogEvent(vmservice.Event event) { + final String message = processVmServiceMessage(event); + globals.printStatus(message); + } + + _stdOutSub = _vmService.onStdoutEvent.listen(onLogEvent); + _stdErrSub = _vmService.onStderrEvent.listen(onLogEvent); _extensionEventSub = _vmService.onExtensionEvent.listen(printStructuredErrorLog); try { diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index d8e7c7412bb..6e5266cc957 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart @@ -24,6 +24,7 @@ import '../macos/xcode.dart'; import '../mdns_discovery.dart'; import '../project.dart'; import '../protocol_discovery.dart'; +import '../vmservice.dart'; import 'fallback_discovery.dart'; import 'ios_deploy.dart'; import 'ios_workflow.dart'; @@ -678,7 +679,7 @@ class IOSDeviceLogReader extends DeviceLogReader { } void logMessage(vm_service.Event event) { - final String message = utf8.decode(base64.decode(event.bytes)); + final String message = processVmServiceMessage(event); if (message.isNotEmpty) { _linesController.add(message); } diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart index 5418dd47aa7..36c0172ed9b 100644 --- a/packages/flutter_tools/lib/src/vmservice.dart +++ b/packages/flutter_tools/lib/src/vmservice.dart @@ -900,3 +900,13 @@ enum Brightness { /// For example, the color might be bright white, requiring black text. light, } + +/// Process a VM service log event into a string message. +String processVmServiceMessage(vm_service.Event event) { + final String message = utf8.decode(base64.decode(event.bytes)); + // Remove extra trailing newlines appended by the vm service. + if (message.endsWith('\n')) { + return message.substring(0, message.length - 1); + } + return message; +} diff --git a/packages/flutter_tools/test/general.shard/vmservice_test.dart b/packages/flutter_tools/test/general.shard/vmservice_test.dart index ec5acae9a3c..9587c3ae45a 100644 --- a/packages/flutter_tools/test/general.shard/vmservice_test.dart +++ b/packages/flutter_tools/test/general.shard/vmservice_test.dart @@ -402,6 +402,16 @@ void main() { expect(vmService.httpAddress, null); expect(vmService.wsAddress, null); }); + + testWithoutContext('Can process log events from the vm service', () { + final vm_service.Event event = vm_service.Event( + bytes: base64.encode(utf8.encode('Hello There\n')), + timestamp: 0, + kind: vm_service.EventKind.kLogging, + ); + + expect(processVmServiceMessage(event), 'Hello There'); + }); } class MockDevice extends Mock implements Device {}