Fix handling of files with spaces in frontend_server_client (#1382)

Fixes https://github.com/dart-lang/webdev/issues/1380

Also enables running of the tests on windows/linux.
diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml
index 7046a4f..926e02b 100644
--- a/.github/workflows/dart.yml
+++ b/.github/workflows/dart.yml
@@ -1,4 +1,4 @@
-# Created with package:mono_repo v5.0.0
+# Created with package:mono_repo v5.0.2
 name: Dart CI
 on:
   push:
@@ -28,48 +28,16 @@
           restore-keys: |
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: dart-lang/setup-dart@v1.2
         with:
           sdk: stable
       - id: checkout
         uses: actions/checkout@v2.3.4
       - name: mono_repo self validate
-        run: dart pub global activate mono_repo 5.0.0
+        run: dart pub global activate mono_repo 5.0.2
       - name: mono_repo self validate
         run: dart pub global run mono_repo generate --validate
   job_002:
-    name: "analyzer_and_format; linux; Dart 2.12.0; PKG: frontend_server_client; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`"
-    runs-on: ubuntu-latest
-    steps:
-      - name: Cache Pub hosted dependencies
-        uses: actions/cache@v2.1.6
-        with:
-          path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:frontend_server_client;commands:format-analyze"
-          restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:frontend_server_client
-            os:ubuntu-latest;pub-cache-hosted;dart:2.12.0
-            os:ubuntu-latest;pub-cache-hosted
-            os:ubuntu-latest
-      - uses: dart-lang/setup-dart@v1.0
-        with:
-          sdk: "2.12.0"
-      - id: checkout
-        uses: actions/checkout@v2.3.4
-      - id: frontend_server_client_pub_upgrade
-        name: frontend_server_client; dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: frontend_server_client
-        run: dart pub upgrade
-      - name: "frontend_server_client; dart format --output=none --set-exit-if-changed ."
-        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
-        working-directory: frontend_server_client
-        run: "dart format --output=none --set-exit-if-changed ."
-      - name: "frontend_server_client; dart analyze --fatal-infos ."
-        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
-        working-directory: frontend_server_client
-        run: dart analyze --fatal-infos .
-  job_003:
     name: "analyzer_and_format; linux; Dart dev; PKG: dwds; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`, `dart test test/build/ensure_version_test.dart`"
     runs-on: ubuntu-latest
     steps:
@@ -83,7 +51,7 @@
             os:ubuntu-latest;pub-cache-hosted;dart:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: dart-lang/setup-dart@v1.2
         with:
           sdk: dev
       - id: checkout
@@ -105,21 +73,21 @@
         if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'"
         working-directory: dwds
         run: dart test test/build/ensure_version_test.dart
-  job_004:
-    name: "analyzer_and_format; linux; Dart dev; PKGS: example, fixtures/_webdevSmoke, frontend_server_common; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`"
+  job_003:
+    name: "analyzer_and_format; linux; Dart dev; PKGS: example, fixtures/_webdevSmoke, frontend_server_client, frontend_server_common; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
         uses: actions/cache@v2.1.6
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:example-fixtures/_webdevSmoke-frontend_server_common;commands:format-analyze"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:example-fixtures/_webdevSmoke-frontend_server_client-frontend_server_common;commands:format-analyze"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:example-fixtures/_webdevSmoke-frontend_server_common
+            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:example-fixtures/_webdevSmoke-frontend_server_client-frontend_server_common
             os:ubuntu-latest;pub-cache-hosted;dart:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: dart-lang/setup-dart@v1.2
         with:
           sdk: dev
       - id: checkout
@@ -150,6 +118,19 @@
         if: "always() && steps.fixtures__webdevSmoke_pub_upgrade.conclusion == 'success'"
         working-directory: fixtures/_webdevSmoke
         run: dart analyze --fatal-infos .
+      - id: frontend_server_client_pub_upgrade
+        name: frontend_server_client; dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart pub upgrade
+      - name: "frontend_server_client; dart format --output=none --set-exit-if-changed ."
+        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: "dart format --output=none --set-exit-if-changed ."
+      - name: "frontend_server_client; dart analyze --fatal-infos ."
+        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart analyze --fatal-infos .
       - id: frontend_server_common_pub_upgrade
         name: frontend_server_common; dart pub upgrade
         if: "always() && steps.checkout.conclusion == 'success'"
@@ -163,7 +144,7 @@
         if: "always() && steps.frontend_server_common_pub_upgrade.conclusion == 'success'"
         working-directory: frontend_server_common
         run: dart analyze --fatal-infos .
-  job_005:
+  job_004:
     name: "analyzer_and_format; linux; Dart dev; PKG: webdev; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`, `dart test test/build/ensure_build_test.dart`"
     runs-on: ubuntu-latest
     steps:
@@ -177,7 +158,7 @@
             os:ubuntu-latest;pub-cache-hosted;dart:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: dart-lang/setup-dart@v1.2
         with:
           sdk: dev
       - id: checkout
@@ -199,7 +180,7 @@
         if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'"
         working-directory: webdev
         run: dart test test/build/ensure_build_test.dart
-  job_006:
+  job_005:
     name: "unit_test; linux; Dart dev; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test`"
     runs-on: ubuntu-latest
     steps:
@@ -213,7 +194,7 @@
             os:ubuntu-latest;pub-cache-hosted;dart:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: dart-lang/setup-dart@v1.2
         with:
           sdk: dev
       - id: checkout
@@ -236,7 +217,39 @@
       - job_002
       - job_003
       - job_004
-      - job_005
+  job_006:
+    name: "unit_test; linux; Dart dev; PKG: frontend_server_client; `dart test`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2.1.6
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:frontend_server_client;commands:test_1"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:frontend_server_client
+            os:ubuntu-latest;pub-cache-hosted;dart:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v1.2
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2.3.4
+      - id: frontend_server_client_pub_upgrade
+        name: frontend_server_client; dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart pub upgrade
+      - name: frontend_server_client; dart test
+        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
   job_007:
     name: "unit_test; linux; Dart dev; PKG: webdev; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test -j 1`"
     runs-on: ubuntu-latest
@@ -251,7 +264,7 @@
             os:ubuntu-latest;pub-cache-hosted;dart:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: dart-lang/setup-dart@v1.2
         with:
           sdk: dev
       - id: checkout
@@ -274,12 +287,44 @@
       - job_002
       - job_003
       - job_004
-      - job_005
   job_008:
+    name: "unit_test; linux; Dart stable; PKG: frontend_server_client; `dart test`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2.1.6
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:stable;packages:frontend_server_client;commands:test_1"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:stable;packages:frontend_server_client
+            os:ubuntu-latest;pub-cache-hosted;dart:stable
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v1.2
+        with:
+          sdk: stable
+      - id: checkout
+        uses: actions/checkout@v2.3.4
+      - id: frontend_server_client_pub_upgrade
+        name: frontend_server_client; dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart pub upgrade
+      - name: frontend_server_client; dart test
+        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_009:
     name: "unit_test; windows; Dart dev; PKG: dwds; `dart test`"
     runs-on: windows-latest
     steps:
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: dart-lang/setup-dart@v1.2
         with:
           sdk: dev
       - id: checkout
@@ -298,12 +343,34 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-  job_009:
+  job_010:
+    name: "unit_test; windows; Dart dev; PKG: frontend_server_client; `dart test`"
+    runs-on: windows-latest
+    steps:
+      - uses: dart-lang/setup-dart@v1.2
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2.3.4
+      - id: frontend_server_client_pub_upgrade
+        name: frontend_server_client; dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart pub upgrade
+      - name: frontend_server_client; dart test
+        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_011:
     name: "unit_test; windows; Dart dev; PKG: webdev; `dart test -j 1`"
     runs-on: windows-latest
     steps:
-      - uses: dart-lang/setup-dart@v1.0
+      - uses: dart-lang/setup-dart@v1.2
         with:
           sdk: dev
       - id: checkout
@@ -322,8 +389,30 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-  job_010:
+  job_012:
+    name: "unit_test; windows; Dart stable; PKG: frontend_server_client; `dart test`"
+    runs-on: windows-latest
+    steps:
+      - uses: dart-lang/setup-dart@v1.2
+        with:
+          sdk: stable
+      - id: checkout
+        uses: actions/checkout@v2.3.4
+      - id: frontend_server_client_pub_upgrade
+        name: frontend_server_client; dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart pub upgrade
+      - name: frontend_server_client; dart test
+        if: "always() && steps.frontend_server_client_pub_upgrade.conclusion == 'success'"
+        working-directory: frontend_server_client
+        run: dart test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_013:
     name: Notify failure
     runs-on: ubuntu-latest
     if: "(github.event_name == 'push' || github.event_name == 'schedule') && failure()"
@@ -344,3 +433,6 @@
       - job_007
       - job_008
       - job_009
+      - job_010
+      - job_011
+      - job_012
diff --git a/frontend_server_client/CHANGELOG.md b/frontend_server_client/CHANGELOG.md
index f8659ac..c77b290 100644
--- a/frontend_server_client/CHANGELOG.md
+++ b/frontend_server_client/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 2.1.1
+
+- Fix a bug where spaces in the output dill path would cause a parse error when
+  reading the error count output.
+
 ## 2.1.0
 
 - Support enabling experiments when starting the compiler.
diff --git a/frontend_server_client/lib/src/frontend_server_client.dart b/frontend_server_client/lib/src/frontend_server_client.dart
index 0f3a285..b0a83c7 100644
--- a/frontend_server_client/lib/src/frontend_server_client.dart
+++ b/frontend_server_client/lib/src/frontend_server_client.dart
@@ -171,8 +171,8 @@
             if (line.startsWith(feBoundaryKey)) {
               state = _CompileState.done;
               var parts = line.split(' ');
-              outputDillPath = parts[1];
-              errorCount = int.parse(parts[2]);
+              outputDillPath = parts.getRange(1, parts.length - 1).join(' ');
+              errorCount = int.parse(parts.last);
               continue;
             }
             var diffUri = Uri.parse(line.substring(1));
diff --git a/frontend_server_client/mono_pkg.yaml b/frontend_server_client/mono_pkg.yaml
index 40c94b3..a8d5560 100644
--- a/frontend_server_client/mono_pkg.yaml
+++ b/frontend_server_client/mono_pkg.yaml
@@ -4,4 +4,12 @@
     - group:
       - format
       - analyze: --fatal-infos .
-      dart: [2.12.0]
+      dart: dev
+  - unit_test:
+    - test:
+      dart:
+        - stable
+        - dev
+      os:
+        - windows
+        - linux
diff --git a/frontend_server_client/pubspec.yaml b/frontend_server_client/pubspec.yaml
index 00c0830..63898c9 100644
--- a/frontend_server_client/pubspec.yaml
+++ b/frontend_server_client/pubspec.yaml
@@ -1,5 +1,5 @@
 name: frontend_server_client
-version: 2.1.0
+version: 2.1.1
 description: >-
   Client code to start and interact with the frontend_server compiler from the
   Dart SDK.
diff --git a/frontend_server_client/test/frontend_sever_client_test.dart b/frontend_server_client/test/frontend_sever_client_test.dart
index 3231225..d0b00a8 100644
--- a/frontend_server_client/test/frontend_sever_client_test.dart
+++ b/frontend_server_client/test/frontend_sever_client_test.dart
@@ -94,7 +94,7 @@
     var vmService = await vmServiceConnectUri(observatoryUri);
     var isolate = await waitForIsolatesAndResume(vmService);
 
-    expect(await stdoutLines.next, p.join('hello', 'world'));
+    await expectLater(stdoutLines, emitsThrough(p.join('hello', 'world')));
 
     var appFile = File(entrypoint);
     var originalContent = await appFile.readAsString();
@@ -117,7 +117,10 @@
 
     expect(await stdoutLines.next, p.join('goodbye', 'world'));
     expect(await process.exitCode, 0);
-  });
+  },
+      skip: Platform.isWindows
+          ? 'https://github.com/dart-lang/webdev/issues/1383'
+          : false);
 
   test('can handle compile errors and reload fixes', () async {
     var entrypoint = p.join(packageRoot, 'bin', 'main.dart');
@@ -165,7 +168,7 @@
 
     // The program actually runs regardless of the errors, as they don't affect
     // the runtime behavior.
-    expect(await stdoutLines.next, p.join('hello', 'world'));
+    await expectLater(stdoutLines, emitsThrough(p.join('hello', 'world')));
 
     await entrypointFile
         .writeAsString(originalContent.replaceFirst('hello', 'goodbye'));
@@ -184,7 +187,10 @@
 
     expect(await stdoutLines.next, p.join('goodbye', 'world'));
     expect(await process.exitCode, 0);
-  });
+  },
+      skip: Platform.isWindows
+          ? 'https://github.com/dart-lang/webdev/issues/1383'
+          : false);
 
   test('can compile and recompile a dartdevc app', () async {
     var entrypoint =
@@ -264,6 +270,59 @@
     expect(result.errorCount, 1);
     expect(result.compilerOutputLines, contains(contains('int x;')));
   });
+
+  test('can compile and recompile filenames with spaces', () async {
+    await d.dir('a', [
+      d.dir('bin', [
+        d.file('main with spaces.dart', '''
+void main() {
+  print('hello world');
+}
+''')
+      ]),
+    ]).create();
+
+    var entrypoint = p.join(packageRoot, 'bin', 'main with spaces.dart');
+    client = await FrontendServerClient.start(entrypoint,
+        p.join(packageRoot, 'out with spaces.dill'), vmPlatformDill);
+    var result = await client.compile();
+    if (result == null) {
+      fail('Expected compilation to be non-null');
+    }
+    client.accept();
+    expect(result.compilerOutputLines, isEmpty);
+    expect(result.errorCount, 0);
+    expect(
+        result.newSources,
+        containsAll([
+          File(entrypoint).uri,
+        ]));
+    expect(result.removedSources, isEmpty);
+    expect(File(result.dillOutput).existsSync(), true);
+    var processResult =
+        await Process.run(Platform.resolvedExecutable, [result.dillOutput]);
+
+    expect(processResult.stdout, startsWith('hello world'));
+    expect(processResult.exitCode, 0);
+
+    var appFile = File(entrypoint);
+    var originalContent = await appFile.readAsString();
+    var newContent = originalContent.replaceFirst('hello', 'goodbye');
+    await appFile.writeAsString(newContent);
+    result = await client.compile([appFile.uri]);
+    if (result == null) {
+      fail('Expected compilation to be non-null');
+    }
+    expect(result.compilerOutputLines, isEmpty);
+    expect(result.errorCount, 0);
+    expect(result.newSources, isEmpty);
+    expect(result.removedSources, isEmpty);
+
+    processResult =
+        await Process.run(Platform.resolvedExecutable, [result.dillOutput]);
+    expect(processResult.stdout, startsWith('goodbye world'));
+    expect(processResult.exitCode, 0);
+  });
 }
 
 Future<Isolate> waitForIsolatesAndResume(VmService vmService) async {
diff --git a/tool/ci.sh b/tool/ci.sh
index e0a2dfa..716288c 100755
--- a/tool/ci.sh
+++ b/tool/ci.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Created with package:mono_repo v5.0.0
+# Created with package:mono_repo v5.0.2
 
 # Support built in commands on windows out of the box.
 # When it is a flutter repo (check the pubspec.yaml for "sdk: flutter")