Skip to content

Commit 3f038ae

Browse files
authored
[flutter_tools] Fix encoded stderr in "dart.log" from debug adapter to client (flutter#155249)
To aid debugging, debug adapter (DAP) clients can ask the debug adapters to send verbose logs back to the client (so they can capture them in a client-side log along with other things happening on the client). Included in this log is the `stderr` output of the `flutter run` process spawned by the debug adapter. This output was not decoded correctly for these logs, so showed up like: ``` [Flutter] [stderr] [91, 32, 32, 43, 49, 52, 32, 109, 115, 93, 32, 67, 111, 117, 108, 100, 32, 110, 111, 116, 32, 102, 105, 110, 100, 32, 97, 110, 32, 111, 112, 116, 105, 111, 110, 32, 110, 97, 109, 101, 100, 32, 34, 105, 110, 118, 97, 108, 105, 100, 34, 46, 10, 10, 91, 32, 32, 32, 32, 32, 32, 32, 32, 93, 32, 82, 117, 110, 32, 39, 102, 108, 117, 116, 116, 101, 114, 32, 45, 104, 39, 32, 40, 111, 114, 32, 39, 102, 108, 117, 116, 116, 101, 114, 32, 60, 99, 111, 109, 109, 97, 110, 100, 62, 32, 45, 104, 39, 41, 32, 102, 111, 114, 32, 97, 118, 97, 105, 108, 97, 98, 108, 101, 32, 102, 108, 117, 116, 116, 101, 114, 32, 99, 111, 109, 109, 97, 110, 100, 115, 32, 97, 110, 100, 32, 111, 112, 116, 105, 111, 110, 115, 46, 10] ``` This change decodes the output before processing. Fixes Dart-Code/Dart-Code#5268 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1 parent 5b5cfa2 commit 3f038ae

File tree

4 files changed

+37
-7
lines changed

4 files changed

+37
-7
lines changed

packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,9 +603,9 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter with VmServiceInfoFile
603603
}
604604

605605
@override
606-
void handleStderr(List<int> data) {
606+
void handleStderr(String data) {
607607
_logTraffic('<== [Flutter] [stderr] $data');
608-
sendOutput('stderr', utf8.decode(data));
608+
sendOutput('stderr', data);
609609
}
610610

611611
/// Handles stdout from the `flutter run --machine` process, decoding the JSON and calling the appropriate handlers.

packages/flutter_tools/lib/src/debug_adapters/flutter_base_adapter.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import '../base/file_system.dart';
1111
import '../base/io.dart';
1212
import '../base/platform.dart';
1313
import '../cache.dart';
14+
import '../convert.dart';
1415
import 'flutter_adapter_args.dart';
1516
import 'mixins.dart';
1617

@@ -150,11 +151,11 @@ abstract class FlutterBaseDebugAdapter extends DartDebugAdapter<FlutterLaunchReq
150151
this.process = process;
151152

152153
process.stdout.transform(ByteToLineTransformer()).listen(handleStdout);
153-
process.stderr.listen(handleStderr);
154+
process.stderr.transform(utf8.decoder).listen(handleStderr);
154155
unawaited(process.exitCode.then(handleExitCode));
155156
}
156157

157158
void handleExitCode(int code);
158-
void handleStderr(List<int> data);
159+
void handleStderr(String data);
159160
void handleStdout(String data);
160161
}

packages/flutter_tools/lib/src/debug_adapters/flutter_test_adapter.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ class FlutterTestDebugAdapter extends FlutterBaseDebugAdapter with TestAdapter {
105105
}
106106

107107
@override
108-
void handleStderr(List<int> data) {
108+
void handleStderr(String data) {
109109
logger?.call('stderr: $data');
110-
sendOutput('stderr', utf8.decode(data));
110+
sendOutput('stderr', data);
111111
}
112112

113113
/// Handles stdout from the `flutter test --machine` process, decoding the JSON and calling the appropriate handlers.

packages/flutter_tools/test/integration.shard/debug_adapter/flutter_adapter_test.dart

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void main() {
7474
);
7575
});
7676

77-
testWithoutContext('logs to client when sendLogsToClient=true', () async {
77+
testWithoutContext('logs stdout to client when sendLogsToClient=true', () async {
7878
final BasicProject project = BasicProject();
7979
await project.setUpIn(tempDir);
8080

@@ -107,6 +107,35 @@ void main() {
107107
);
108108
});
109109

110+
testWithoutContext('logs stderr to client when sendLogsToClient=true', () async {
111+
final BasicProject project = BasicProject();
112+
await project.setUpIn(tempDir);
113+
114+
// Capture all log events.
115+
final Future<List<Event>> logEventsFuture = dap.client.events('dart.log').toList();
116+
117+
// Launch the app and wait for it to terminate (because of the error).
118+
await Future.wait(<Future<void>>[
119+
dap.client.event('terminated'),
120+
dap.client.start(
121+
launch: () => dap.client.launch(
122+
cwd: project.dir.path,
123+
noDebug: true,
124+
toolArgs: <String>['--not-a-valid-flag'],
125+
sendLogsToClient: true,
126+
),
127+
),
128+
], eagerError: true);
129+
130+
// Ensure logs contain the expected error message.
131+
final List<Event> logEvents = await logEventsFuture;
132+
final List<String> logMessages = logEvents.map((Event l) => (l.body! as Map<String, Object?>)['message']! as String).toList();
133+
expect(
134+
logMessages,
135+
contains(startsWith('<== [Flutter] [stderr] Could not find an option named "not-a-valid-flag"')),
136+
);
137+
});
138+
110139
testWithoutContext('can run and terminate a Flutter app in noDebug mode', () async {
111140
final BasicProject project = BasicProject();
112141
await project.setUpIn(tempDir);

0 commit comments

Comments
 (0)