dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.11k stars 1.57k forks source link

stdout.supportsAnsiEscapes has some weird effect on Windows #45137

Open jensjoha opened 3 years ago

jensjoha commented 3 years ago

On master (f2dfe3a8be24db64c924541c2775ef496171c02b) running python tools/test.py -n dartk-win-release-x64 standalone_2/io/process_shell_test passes.

Applying this patch though:

diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 0fcaf1873e2..92124f840f9 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -872,6 +872,7 @@ Future _processLoadRequest(request) async {
     CompilerResult compilerResult = await compiler.compile(script);
     Set<Library> loadedLibraries = compilerResult.loadedLibraries;

+    stdout.supportsAnsiEscapes;
     if (compiler.errors.isNotEmpty) {
       if (compilerResult.component != null) {
         result = new CompilationResult.errors(

compiles and runs again, and it doesn't:

stderr:
Unhandled exception:
wrong number of args: [a b] vs [a b
]
#0      testRunShell.test.<anonymous closure> (file:///C:/src/dart-sdk/sdk/tests/standalone_2/io/process_shell_test.dart:33:9)
<asynchronous suspension>

It doesn't even fail the same way every time:

stderr:
Unhandled exception:
wrong number of args: ["] vs ["
]
#0      testRunShell.test.<anonymous closure> (file:///C:/src/dart-sdk/sdk/tests/standalone_2/io/process_shell_test.dart:33:9)
<asynchronous suspension>

Notice that the test explicitly splits the stdout with "\r\n" on Windows, and changing that to new RegExp('\\r?\\n') makes it pass --- so it's something with lineendings somehow. Making the test print the code units:

diff --git a/tests/standalone_2/io/process_shell_test.dart b/tests/standalone_2/io/process_shell_test.dart
index e561315b5e3..8649aa20cda 100644
--- a/tests/standalone_2/io/process_shell_test.dart
+++ b/tests/standalone_2/io/process_shell_test.dart
@@ -24,6 +24,7 @@ void testRunShell() {
             runInShell: true)
         .then((process_result) {
       var result;
+      print(process_result.stdout.toString().codeUnits);
       if (Platform.operatingSystem == "windows") {
         result = process_result.stdout.split("\r\n");
       } else {

gives for instance

stdout:
unittest-suite-wait-for-done
[34, 10]

stderr:
Unhandled exception:
wrong number of args: ["] vs ["
]
#0      testRunShell.test.<anonymous closure> (file:///C:/src/dart-sdk/sdk/tests/standalone_2/io/process_shell_test.dart:34:9)
<asynchronous suspension>

so it got "\n --- not the expected "\r\n.

jensjoha commented 3 years ago

Update: The reason it doesn't always fail the same way is that it does async code that is not awaited...

jensjoha commented 3 years ago

Another update: I can reproduce without recompiling dart:

Create a file with this content:

import "dart:io";

main(List<String> args) {
  if (args.where((arg) => arg == "subcall").isEmpty) {
    ProcessResult runResult = Process.runSync(
      Platform.resolvedExecutable,
      [Platform.script.toString(), "subcall", ...args],
      runInShell: true,
    );
    print(runResult.stdout.toString().codeUnits);
  } else {
    if (args.where((arg) => arg == "--ansi").isNotEmpty) {
      stdout.supportsAnsiEscapes;
    }
    print("hello");
    print("world");
  }
}

and run it with and without the --ansi argument:

PS C:\src\dart-sdk\sdk> .\out\ReleaseX64\dart.exe t2.dart
[104, 101, 108, 108, 111, 13, 10, 119, 111, 114, 108, 100, 13, 10]
PS C:\src\dart-sdk\sdk> .\out\ReleaseX64\dart.exe t2.dart --ansi
[104, 101, 108, 108, 111, 10, 119, 111, 114, 108, 100, 10]

Without the --ansi argument (i.e. without the script in the subcall having the stdout.supportsAnsiEscapes; call) it uses 13 10 (i.e. \r\n), and with the --ansi argument it just uses 10 (i.e. \n).