Merge branch 'master' into top-level-equals
diff --git a/.github/ISSUE_TEMPLATE/01_test_runner_bug.md b/.github/ISSUE_TEMPLATE/01_test_runner_bug.md
new file mode 100644
index 0000000..e49d277
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/01_test_runner_bug.md
@@ -0,0 +1,14 @@
+---
+name: I found a bug in the test runner
+about: >-
+  Report a bug in running tests, integration with a specific platform, or
+  any behavior of 'package:test'.
+title: ''
+labels: bug
+---
+Describe the bug in detail.
+Include the specific command you ran and any relevant details about the
+environment, including operating system, Dart SDK version, and the version of
+`package:test` you are using.
+Whenever possible, include a full reproduction example that we can run to
+observe the problem.
diff --git a/.github/ISSUE_TEMPLATE/02_test_runner_feature.md b/.github/ISSUE_TEMPLATE/02_test_runner_feature.md
new file mode 100644
index 0000000..56170ba
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/02_test_runner_feature.md
@@ -0,0 +1,10 @@
+---
+name: I'd like a new feature in the test runner
+about: >-
+  Propose a feature for 'package:test' that would make testing easier or more
+  powerful.
+title: ''
+labels: enhancement
+---
+Describe the feature and include specific description of the use case, or use
+cases, you have in mind.
diff --git a/.github/ISSUE_TEMPLATE/03_checks_feedback.md b/.github/ISSUE_TEMPLATE/03_checks_feedback.md
new file mode 100644
index 0000000..5eb0039
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/03_checks_feedback.md
@@ -0,0 +1,8 @@
+---
+name: I have feedback for the package:checks preview
+about: Suggest a change, new feature, or bug, for 'package:checks'.
+title: ''
+labels: package:checks
+---
+Add any feedback about `package:checks`.
+Include a description of a specific use case for any feature requests.
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 9523511..99e98e3 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -2,8 +2,28 @@
 # See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates
 
 version: 2
-updates: 
-  - package-ecosystem: github-actions
-    directory: /
+
+updates:
+  - package-ecosystem: "github-actions"
+    directory: "/"
     schedule:
-      interval: monthly
+      interval: "monthly"
+    labels:
+      - "autosubmit"
+
+  # Check daily for major version dependency updates for packages which depend
+  # on package:analyzer.
+  - package-ecosystem: "pub"
+    directory: "pkgs/test"
+    schedule:
+      interval: "daily"
+    versioning-strategy: increase-if-necessary
+    reviewers:
+      - "natebosch"
+  - package-ecosystem: "pub"
+    directory: "pkgs/test_core"
+    schedule:
+      interval: "daily"
+    versioning-strategy: increase-if-necessary
+    reviewers:
+      - "natebosch"
diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml
index c411012..098eab1 100644
--- a/.github/workflows/dart.yml
+++ b/.github/workflows/dart.yml
@@ -1,4 +1,4 @@
-# Created with package:mono_repo v6.5.0
+# Created with package:mono_repo v6.5.7
 name: Dart CI
 on:
   push:
@@ -21,7 +21,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable"
@@ -29,71 +29,37 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: stable
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - name: mono_repo self validate
-        run: dart pub global activate mono_repo 6.5.0
+        run: dart pub global activate mono_repo 6.5.7
       - name: mono_repo self validate
         run: dart pub global run mono_repo generate --validate
   job_002:
-    name: "analyze_and_format; linux; Dart 2.18.0; PKG: legacy_tests/nnbd_opted_in_with_optout; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos`"
+    name: "analyze_and_format; linux; Dart 3.0.0; PKGS: pkgs/checks, pkgs/test_core; `dart analyze`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/nnbd_opted_in_with_optout;commands:format-analyze_0"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/checks-pkgs/test_core;commands:analyze_1"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/nnbd_opted_in_with_optout
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/checks-pkgs/test_core
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_nnbd_opted_in_with_optout_pub_upgrade
-        name: legacy_tests/nnbd_opted_in_with_optout; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in_with_optout
-      - name: "legacy_tests/nnbd_opted_in_with_optout; dart format --output=none --set-exit-if-changed ."
-        run: "dart format --output=none --set-exit-if-changed ."
-        if: "always() && steps.legacy_tests_nnbd_opted_in_with_optout_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in_with_optout
-      - name: "legacy_tests/nnbd_opted_in_with_optout; dart analyze --fatal-infos"
-        run: dart analyze --fatal-infos
-        if: "always() && steps.legacy_tests_nnbd_opted_in_with_optout_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in_with_optout
-  job_003:
-    name: "analyze_and_format; linux; Dart 2.18.0; PKGS: pkgs/checks, pkgs/test_core; `dart analyze`"
-    runs-on: ubuntu-latest
-    steps:
-      - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
-        with:
-          path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/checks-pkgs/test_core;commands:analyze_1"
-          restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/checks-pkgs/test_core
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
-            os:ubuntu-latest;pub-cache-hosted
-            os:ubuntu-latest
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_checks_pub_upgrade
         name: pkgs/checks; dart pub upgrade
         run: dart pub upgrade
@@ -112,27 +78,27 @@
         run: dart analyze
         if: "always() && steps.pkgs_test_core_pub_upgrade.conclusion == 'success'"
         working-directory: pkgs/test_core
-  job_004:
-    name: "analyze_and_format; linux; Dart dev; PKGS: integration_tests/spawn_hybrid, legacy_tests/nnbd_opted_in, pkgs/checks, pkgs/test, pkgs/test_api, pkgs/test_core; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos`"
+  job_003:
+    name: "analyze_and_format; linux; Dart dev; PKGS: integration_tests/spawn_hybrid, pkgs/checks, pkgs/test, pkgs/test_api, pkgs/test_core; `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@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:integration_tests/spawn_hybrid-legacy_tests/nnbd_opted_in-pkgs/checks-pkgs/test-pkgs/test_api-pkgs/test_core;commands:format-analyze_0"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:integration_tests/spawn_hybrid-pkgs/checks-pkgs/test-pkgs/test_api-pkgs/test_core;commands:format-analyze_0"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:integration_tests/spawn_hybrid-legacy_tests/nnbd_opted_in-pkgs/checks-pkgs/test-pkgs/test_api-pkgs/test_core
+            os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:integration_tests/spawn_hybrid-pkgs/checks-pkgs/test-pkgs/test_api-pkgs/test_core
             os:ubuntu-latest;pub-cache-hosted;sdk:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: integration_tests_spawn_hybrid_pub_upgrade
         name: integration_tests/spawn_hybrid; dart pub upgrade
         run: dart pub upgrade
@@ -146,19 +112,6 @@
         run: dart analyze --fatal-infos
         if: "always() && steps.integration_tests_spawn_hybrid_pub_upgrade.conclusion == 'success'"
         working-directory: integration_tests/spawn_hybrid
-      - id: legacy_tests_nnbd_opted_in_pub_upgrade
-        name: legacy_tests/nnbd_opted_in; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in
-      - name: "legacy_tests/nnbd_opted_in; dart format --output=none --set-exit-if-changed ."
-        run: "dart format --output=none --set-exit-if-changed ."
-        if: "always() && steps.legacy_tests_nnbd_opted_in_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in
-      - name: "legacy_tests/nnbd_opted_in; dart analyze --fatal-infos"
-        run: dart analyze --fatal-infos
-        if: "always() && steps.legacy_tests_nnbd_opted_in_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in
       - id: pkgs_checks_pub_upgrade
         name: pkgs/checks; dart pub upgrade
         run: dart pub upgrade
@@ -211,12 +164,12 @@
         run: dart analyze --fatal-infos
         if: "always() && steps.pkgs_test_core_pub_upgrade.conclusion == 'success'"
         working-directory: pkgs/test_core
-  job_005:
+  job_004:
     name: "analyze_and_format; linux; Dart main; PKG: integration_tests/wasm; `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@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:integration_tests/wasm;commands:format-analyze_0"
@@ -226,12 +179,12 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: main
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: integration_tests_wasm_pub_upgrade
         name: integration_tests/wasm; dart pub upgrade
         run: dart pub upgrade
@@ -245,74 +198,27 @@
         run: dart analyze --fatal-infos
         if: "always() && steps.integration_tests_wasm_pub_upgrade.conclusion == 'success'"
         working-directory: integration_tests/wasm
-  job_006:
-    name: "analyze_and_format; linux; Dart stable; PKGS: legacy_tests/nnbd_opted_out, legacy_tests/spawn_hybrid_with_optout; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos`"
+  job_005:
+    name: "unit_test; linux; Dart 3.0.0; PKG: integration_tests/spawn_hybrid; `dart test -p chrome,vm,node`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:legacy_tests/nnbd_opted_out-legacy_tests/spawn_hybrid_with_optout;commands:format-analyze_0"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:integration_tests/spawn_hybrid;commands:test_0"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:legacy_tests/nnbd_opted_out-legacy_tests/spawn_hybrid_with_optout
-            os:ubuntu-latest;pub-cache-hosted;sdk:stable
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:integration_tests/spawn_hybrid
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: stable
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_nnbd_opted_out_pub_upgrade
-        name: legacy_tests/nnbd_opted_out; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_out
-      - name: "legacy_tests/nnbd_opted_out; dart format --output=none --set-exit-if-changed ."
-        run: "dart format --output=none --set-exit-if-changed ."
-        if: "always() && steps.legacy_tests_nnbd_opted_out_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_out
-      - name: "legacy_tests/nnbd_opted_out; dart analyze --fatal-infos"
-        run: dart analyze --fatal-infos
-        if: "always() && steps.legacy_tests_nnbd_opted_out_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_out
-      - id: legacy_tests_spawn_hybrid_with_optout_pub_upgrade
-        name: legacy_tests/spawn_hybrid_with_optout; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/spawn_hybrid_with_optout
-      - name: "legacy_tests/spawn_hybrid_with_optout; dart format --output=none --set-exit-if-changed ."
-        run: "dart format --output=none --set-exit-if-changed ."
-        if: "always() && steps.legacy_tests_spawn_hybrid_with_optout_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/spawn_hybrid_with_optout
-      - name: "legacy_tests/spawn_hybrid_with_optout; dart analyze --fatal-infos"
-        run: dart analyze --fatal-infos
-        if: "always() && steps.legacy_tests_spawn_hybrid_with_optout_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/spawn_hybrid_with_optout
-  job_007:
-    name: "unit_test; linux; Dart 2.18.0; PKG: integration_tests/spawn_hybrid; `dart test -p chrome,vm,node`"
-    runs-on: ubuntu-latest
-    steps:
-      - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
-        with:
-          path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:integration_tests/spawn_hybrid;commands:test"
-          restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:integration_tests/spawn_hybrid
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
-            os:ubuntu-latest;pub-cache-hosted
-            os:ubuntu-latest
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: integration_tests_spawn_hybrid_pub_upgrade
         name: integration_tests/spawn_hybrid; dart pub upgrade
         run: dart pub upgrade
@@ -327,177 +233,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_008:
-    name: "unit_test; linux; Dart 2.18.0; PKG: legacy_tests/nnbd_opted_in; `dart test -p chrome,vm,node`"
+  job_006:
+    name: "unit_test; linux; Dart 3.0.0; PKG: pkgs/checks; `dart test`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/nnbd_opted_in;commands:test"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/checks;commands:command_01"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/nnbd_opted_in
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/checks
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_nnbd_opted_in_pub_upgrade
-        name: legacy_tests/nnbd_opted_in; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in
-      - name: "legacy_tests/nnbd_opted_in; dart test -p chrome,vm,node"
-        run: "dart test -p chrome,vm,node"
-        if: "always() && steps.legacy_tests_nnbd_opted_in_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-      - job_005
-      - job_006
-  job_009:
-    name: "unit_test; linux; Dart 2.18.0; PKG: legacy_tests/nnbd_opted_in_with_optout; `dart test -p chrome,vm,node`"
-    runs-on: ubuntu-latest
-    steps:
-      - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
-        with:
-          path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/nnbd_opted_in_with_optout;commands:test"
-          restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/nnbd_opted_in_with_optout
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
-            os:ubuntu-latest;pub-cache-hosted
-            os:ubuntu-latest
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_nnbd_opted_in_with_optout_pub_upgrade
-        name: legacy_tests/nnbd_opted_in_with_optout; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in_with_optout
-      - name: "legacy_tests/nnbd_opted_in_with_optout; dart test -p chrome,vm,node"
-        run: "dart test -p chrome,vm,node"
-        if: "always() && steps.legacy_tests_nnbd_opted_in_with_optout_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in_with_optout
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-      - job_005
-      - job_006
-  job_010:
-    name: "unit_test; linux; Dart 2.18.0; PKG: legacy_tests/nnbd_opted_out; `dart test -p chrome,vm,node`"
-    runs-on: ubuntu-latest
-    steps:
-      - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
-        with:
-          path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/nnbd_opted_out;commands:test"
-          restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/nnbd_opted_out
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
-            os:ubuntu-latest;pub-cache-hosted
-            os:ubuntu-latest
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_nnbd_opted_out_pub_upgrade
-        name: legacy_tests/nnbd_opted_out; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_out
-      - name: "legacy_tests/nnbd_opted_out; dart test -p chrome,vm,node"
-        run: "dart test -p chrome,vm,node"
-        if: "always() && steps.legacy_tests_nnbd_opted_out_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_out
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-      - job_005
-      - job_006
-  job_011:
-    name: "unit_test; linux; Dart 2.18.0; PKG: legacy_tests/spawn_hybrid_with_optout; `dart test -p chrome,vm,node`"
-    runs-on: ubuntu-latest
-    steps:
-      - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
-        with:
-          path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/spawn_hybrid_with_optout;commands:test"
-          restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:legacy_tests/spawn_hybrid_with_optout
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
-            os:ubuntu-latest;pub-cache-hosted
-            os:ubuntu-latest
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_spawn_hybrid_with_optout_pub_upgrade
-        name: legacy_tests/spawn_hybrid_with_optout; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/spawn_hybrid_with_optout
-      - name: "legacy_tests/spawn_hybrid_with_optout; dart test -p chrome,vm,node"
-        run: "dart test -p chrome,vm,node"
-        if: "always() && steps.legacy_tests_spawn_hybrid_with_optout_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/spawn_hybrid_with_optout
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-      - job_005
-      - job_006
-  job_012:
-    name: "unit_test; linux; Dart 2.18.0; PKG: pkgs/checks; `dart test`"
-    runs-on: ubuntu-latest
-    steps:
-      - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
-        with:
-          path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/checks;commands:command_00"
-          restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/checks
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
-            os:ubuntu-latest;pub-cache-hosted
-            os:ubuntu-latest
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_checks_pub_upgrade
         name: pkgs/checks; dart pub upgrade
         run: dart pub upgrade
@@ -512,29 +268,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_013:
-    name: "unit_test; linux; Dart 2.18.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 0`"
+  job_007:
+    name: "unit_test; linux; Dart 3.0.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 0`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test;commands:command_01"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test;commands:command_02"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -549,29 +303,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_014:
-    name: "unit_test; linux; Dart 2.18.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 1`"
+  job_008:
+    name: "unit_test; linux; Dart 3.0.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 1`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test;commands:command_02"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test;commands:command_03"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -586,29 +338,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_015:
-    name: "unit_test; linux; Dart 2.18.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 2`"
+  job_009:
+    name: "unit_test; linux; Dart 3.0.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 2`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test;commands:command_03"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test;commands:command_04"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -623,29 +373,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_016:
-    name: "unit_test; linux; Dart 2.18.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 3`"
+  job_010:
+    name: "unit_test; linux; Dart 3.0.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 3`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test;commands:command_04"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test;commands:command_05"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -660,29 +408,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_017:
-    name: "unit_test; linux; Dart 2.18.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 4`"
+  job_011:
+    name: "unit_test; linux; Dart 3.0.0; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 4`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test;commands:command_05"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test;commands:command_06"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -697,29 +443,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_018:
-    name: "unit_test; linux; Dart 2.18.0; PKG: pkgs/test_api; `dart test --preset travis -x browser`"
+  job_012:
+    name: "unit_test; linux; Dart 3.0.0; PKG: pkgs/test_api; `dart test --preset travis -x browser`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test_api;commands:command_11"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test_api;commands:command_12"
           restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0;packages:pkgs/test_api
-            os:ubuntu-latest;pub-cache-hosted;sdk:2.18.0
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/test_api
+            os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_api_pub_upgrade
         name: pkgs/test_api; dart pub upgrade
         run: dart pub upgrade
@@ -734,29 +478,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_019:
+  job_013:
     name: "unit_test; linux; Dart dev; PKG: integration_tests/spawn_hybrid; `dart test -p chrome,vm,node`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:integration_tests/spawn_hybrid;commands:test"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:integration_tests/spawn_hybrid;commands:test_0"
           restore-keys: |
             os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:integration_tests/spawn_hybrid
             os:ubuntu-latest;pub-cache-hosted;sdk:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: integration_tests_spawn_hybrid_pub_upgrade
         name: integration_tests/spawn_hybrid; dart pub upgrade
         run: dart pub upgrade
@@ -771,29 +513,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_020:
+  job_014:
     name: "unit_test; linux; Dart dev; PKG: pkgs/checks; `dart test`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/checks;commands:command_00"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/checks;commands:command_01"
           restore-keys: |
             os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/checks
             os:ubuntu-latest;pub-cache-hosted;sdk:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_checks_pub_upgrade
         name: pkgs/checks; dart pub upgrade
         run: dart pub upgrade
@@ -808,51 +548,12 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_021:
+  job_015:
     name: "unit_test; linux; Dart dev; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 0`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
-        with:
-          path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test;commands:command_01"
-          restore-keys: |
-            os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test
-            os:ubuntu-latest;pub-cache-hosted;sdk:dev
-            os:ubuntu-latest;pub-cache-hosted
-            os:ubuntu-latest
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: dev
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: pkgs_test_pub_upgrade
-        name: pkgs/test; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: pkgs/test
-      - name: "pkgs/test; xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 0"
-        run: "xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 0"
-        if: "always() && steps.pkgs_test_pub_upgrade.conclusion == 'success'"
-        working-directory: pkgs/test
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-      - job_005
-      - job_006
-  job_022:
-    name: "unit_test; linux; Dart dev; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 1`"
-    runs-on: ubuntu-latest
-    steps:
-      - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
           key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test;commands:command_02"
@@ -862,12 +563,47 @@
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
+      - id: pkgs_test_pub_upgrade
+        name: pkgs/test; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: pkgs/test
+      - name: "pkgs/test; xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 0"
+        run: "xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 0"
+        if: "always() && steps.pkgs_test_pub_upgrade.conclusion == 'success'"
+        working-directory: pkgs/test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_016:
+    name: "unit_test; linux; Dart dev; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 1`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test;commands:command_03"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test
+            os:ubuntu-latest;pub-cache-hosted;sdk:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
+        with:
+          sdk: dev
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -882,29 +618,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_023:
+  job_017:
     name: "unit_test; linux; Dart dev; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 2`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test;commands:command_03"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test;commands:command_04"
           restore-keys: |
             os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test
             os:ubuntu-latest;pub-cache-hosted;sdk:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -919,29 +653,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_024:
+  job_018:
     name: "unit_test; linux; Dart dev; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 3`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test;commands:command_04"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test;commands:command_05"
           restore-keys: |
             os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test
             os:ubuntu-latest;pub-cache-hosted;sdk:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -956,29 +688,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_025:
+  job_019:
     name: "unit_test; linux; Dart dev; PKG: pkgs/test; `xvfb-run -s \"-screen 0 1024x768x24\" dart test --preset travis --total-shards 5 --shard-index 4`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test;commands:command_05"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test;commands:command_06"
           restore-keys: |
             os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test
             os:ubuntu-latest;pub-cache-hosted;sdk:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -993,29 +723,27 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_026:
+  job_020:
     name: "unit_test; linux; Dart dev; PKG: pkgs/test_api; `dart test --preset travis -x browser`"
     runs-on: ubuntu-latest
     steps:
       - name: Cache Pub hosted dependencies
-        uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
         with:
           path: "~/.pub-cache/hosted"
-          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test_api;commands:command_11"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test_api;commands:command_12"
           restore-keys: |
             os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/test_api
             os:ubuntu-latest;pub-cache-hosted;sdk:dev
             os:ubuntu-latest;pub-cache-hosted
             os:ubuntu-latest
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_api_pub_upgrade
         name: pkgs/test_api; dart pub upgrade
         run: dart pub upgrade
@@ -1030,19 +758,56 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_027:
-    name: "unit_test; windows; Dart 2.18.0; PKG: integration_tests/spawn_hybrid; `dart test -p chrome,vm,node`"
+  job_021:
+    name: "unit_test; linux; Dart main; PKG: integration_tests/wasm; `pushd /tmp && wget https://dl.google.com/linux/direct/google-chrome-beta_current_amd64.deb && sudo dpkg -i google-chrome-beta_current_amd64.deb && popd && which google-chrome-beta`, `dart test --timeout=60s`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:integration_tests/wasm;commands:command_00-test_1"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;sdk:main;packages:integration_tests/wasm
+            os:ubuntu-latest;pub-cache-hosted;sdk:main
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - name: Setup Dart SDK
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
+        with:
+          sdk: main
+      - id: checkout
+        name: Checkout repository
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
+      - id: integration_tests_wasm_pub_upgrade
+        name: integration_tests/wasm; dart pub upgrade
+        run: dart pub upgrade
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: integration_tests/wasm
+      - name: "integration_tests/wasm; pushd /tmp && wget https://dl.google.com/linux/direct/google-chrome-beta_current_amd64.deb && sudo dpkg -i google-chrome-beta_current_amd64.deb && popd && which google-chrome-beta"
+        run: "pushd /tmp && wget https://dl.google.com/linux/direct/google-chrome-beta_current_amd64.deb && sudo dpkg -i google-chrome-beta_current_amd64.deb && popd && which google-chrome-beta"
+        if: "always() && steps.integration_tests_wasm_pub_upgrade.conclusion == 'success'"
+        working-directory: integration_tests/wasm
+      - name: "integration_tests/wasm; dart test --timeout=60s"
+        run: "dart test --timeout=60s"
+        if: "always() && steps.integration_tests_wasm_pub_upgrade.conclusion == 'success'"
+        working-directory: integration_tests/wasm
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+  job_022:
+    name: "unit_test; windows; Dart 3.0.0; PKG: integration_tests/spawn_hybrid; `dart test -p chrome,vm,node`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: integration_tests_spawn_hybrid_pub_upgrade
         name: integration_tests/spawn_hybrid; dart pub upgrade
         run: dart pub upgrade
@@ -1057,127 +822,17 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_028:
-    name: "unit_test; windows; Dart 2.18.0; PKG: legacy_tests/nnbd_opted_in; `dart test -p chrome,vm,node`"
+  job_023:
+    name: "unit_test; windows; Dart 3.0.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 0`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_nnbd_opted_in_pub_upgrade
-        name: legacy_tests/nnbd_opted_in; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in
-      - name: "legacy_tests/nnbd_opted_in; dart test -p chrome,vm,node"
-        run: "dart test -p chrome,vm,node"
-        if: "always() && steps.legacy_tests_nnbd_opted_in_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-      - job_005
-      - job_006
-  job_029:
-    name: "unit_test; windows; Dart 2.18.0; PKG: legacy_tests/nnbd_opted_in_with_optout; `dart test -p chrome,vm,node`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_nnbd_opted_in_with_optout_pub_upgrade
-        name: legacy_tests/nnbd_opted_in_with_optout; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in_with_optout
-      - name: "legacy_tests/nnbd_opted_in_with_optout; dart test -p chrome,vm,node"
-        run: "dart test -p chrome,vm,node"
-        if: "always() && steps.legacy_tests_nnbd_opted_in_with_optout_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_in_with_optout
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-      - job_005
-      - job_006
-  job_030:
-    name: "unit_test; windows; Dart 2.18.0; PKG: legacy_tests/nnbd_opted_out; `dart test -p chrome,vm,node`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_nnbd_opted_out_pub_upgrade
-        name: legacy_tests/nnbd_opted_out; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_out
-      - name: "legacy_tests/nnbd_opted_out; dart test -p chrome,vm,node"
-        run: "dart test -p chrome,vm,node"
-        if: "always() && steps.legacy_tests_nnbd_opted_out_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/nnbd_opted_out
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-      - job_005
-      - job_006
-  job_031:
-    name: "unit_test; windows; Dart 2.18.0; PKG: legacy_tests/spawn_hybrid_with_optout; `dart test -p chrome,vm,node`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - id: legacy_tests_spawn_hybrid_with_optout_pub_upgrade
-        name: legacy_tests/spawn_hybrid_with_optout; dart pub upgrade
-        run: dart pub upgrade
-        if: "always() && steps.checkout.conclusion == 'success'"
-        working-directory: legacy_tests/spawn_hybrid_with_optout
-      - name: "legacy_tests/spawn_hybrid_with_optout; dart test -p chrome,vm,node"
-        run: "dart test -p chrome,vm,node"
-        if: "always() && steps.legacy_tests_spawn_hybrid_with_optout_pub_upgrade.conclusion == 'success'"
-        working-directory: legacy_tests/spawn_hybrid_with_optout
-    needs:
-      - job_001
-      - job_002
-      - job_003
-      - job_004
-      - job_005
-      - job_006
-  job_032:
-    name: "unit_test; windows; Dart 2.18.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 0`"
-    runs-on: windows-latest
-    steps:
-      - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
-        with:
-          sdk: "2.18.0"
-      - id: checkout
-        name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -1192,19 +847,17 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_033:
-    name: "unit_test; windows; Dart 2.18.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 1`"
+  job_024:
+    name: "unit_test; windows; Dart 3.0.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 1`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -1219,19 +872,17 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_034:
-    name: "unit_test; windows; Dart 2.18.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 2`"
+  job_025:
+    name: "unit_test; windows; Dart 3.0.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 2`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -1246,19 +897,17 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_035:
-    name: "unit_test; windows; Dart 2.18.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 3`"
+  job_026:
+    name: "unit_test; windows; Dart 3.0.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 3`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -1273,19 +922,17 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_036:
-    name: "unit_test; windows; Dart 2.18.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 4`"
+  job_027:
+    name: "unit_test; windows; Dart 3.0.0; PKG: pkgs/test; `dart test --preset travis --total-shards 5 --shard-index 4`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
-          sdk: "2.18.0"
+          sdk: "3.0.0"
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: pkgs_test_pub_upgrade
         name: pkgs/test; dart pub upgrade
         run: dart pub upgrade
@@ -1300,19 +947,17 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_037:
+  job_028:
     name: "unit_test; windows; Dart dev; PKG: integration_tests/spawn_hybrid; `dart test -p chrome,vm,node`"
     runs-on: windows-latest
     steps:
       - name: Setup Dart SDK
-        uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+        uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: dev
       - id: checkout
         name: Checkout repository
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
       - id: integration_tests_spawn_hybrid_pub_upgrade
         name: integration_tests/spawn_hybrid; dart pub upgrade
         run: dart pub upgrade
@@ -1327,9 +972,7 @@
       - job_002
       - job_003
       - job_004
-      - job_005
-      - job_006
-  job_038:
+  job_029:
     name: Notify failure
     runs-on: ubuntu-latest
     if: "(github.event_name == 'push' || github.event_name == 'schedule') && failure()"
@@ -1369,12 +1012,3 @@
       - job_026
       - job_027
       - job_028
-      - job_029
-      - job_030
-      - job_031
-      - job_032
-      - job_033
-      - job_034
-      - job_035
-      - job_036
-      - job_037
diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml
index c7574c8..dd7bbbc 100644
--- a/.github/workflows/no-response.yml
+++ b/.github/workflows/no-response.yml
@@ -1,12 +1,10 @@
 # A workflow to close issues where the author hasn't responded to a request for
-# more information; see https://github.com/godofredoc/no-response for docs.
+# more information; see https://github.com/actions/stale.
 
 name: No Response
 
-# Both `issue_comment` and `scheduled` event types are required.
+# Run as a daily cron.
 on:
-  issue_comment:
-    types: [created]
   schedule:
     # Every day at 8am
     - cron: '0 8 * * *'
@@ -14,21 +12,24 @@
 # All permissions not specified are set to 'none'.
 permissions:
   issues: write
+  pull-requests: write
 
 jobs:
-  noResponse:
+  no-response:
     runs-on: ubuntu-latest
     if: ${{ github.repository_owner == 'dart-lang' }}
     steps:
-      - uses: godofredoc/no-response@0ce2dc0e63e1c7d2b87752ceed091f6d32c9df09
+      - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84
         with:
-          responseRequiredLabel: "needs-info"
-          responseRequiredColor: 4774bc
-          daysUntilClose: 14
-          # Comment to post when closing an Issue for lack of response.
-          closeComment: >
-            Without additional information we're not able to resolve this
-            issue, so it will be closed at this time. You're still free to add
-            more info and respond to any questions above, though. We'll reopen
-            the case if you do. Thanks for your contribution!
-          token: ${{ github.token }}
+          days-before-stale: -1
+          days-before-close: 14
+          stale-issue-label: "needs-info"
+          close-issue-message: >
+            Without additional information we're not able to resolve this issue.
+            Feel free to add more info or respond to any questions above and we
+            can reopen the case. Thanks for your contribution!
+          stale-pr-label: "needs-info"
+          close-pr-message: >
+            Without additional information we're not able to resolve this PR.
+            Feel free to add more info or respond to any questions above.
+            Thanks for your contribution!
diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml
new file mode 100644
index 0000000..bf40d5f
--- /dev/null
+++ b/.github/workflows/publish.yaml
@@ -0,0 +1,15 @@
+# A CI configuration to auto-publish pub packages.
+
+name: Publish
+
+on:
+  pull_request:
+    branches: [ master ]
+    types: [opened, synchronize, reopened, labeled, unlabeled]
+  push:
+    tags: [ '[A-z]+-v[0-9]+.[0-9]+.[0-9]+*' ]
+
+jobs:
+  publish:
+    if: ${{ github.repository_owner == 'dart-lang' }}
+    uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main
diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
index 80a463a..fcc94b7 100644
--- a/.github/workflows/scorecards-analysis.yml
+++ b/.github/workflows/scorecards-analysis.yml
@@ -22,12 +22,12 @@
 
     steps:
       - name: "Checkout code"
-        uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
+        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
         with:
           persist-credentials: false
 
       - name: "Run analysis"
-        uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86
+        uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031
         with:
           results_file: results.sarif
           results_format: sarif
@@ -50,6 +50,6 @@
 
       # Upload the results to GitHub's code scanning dashboard.
       - name: "Upload to code-scanning"
-        uses: github/codeql-action/upload-sarif@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2.2.1
+        uses: github/codeql-action/upload-sarif@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # v2.21.2
         with:
           sarif_file: results.sarif
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 61f02f2..90003c0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -39,14 +39,32 @@
 `mono_repo` tool. From the root of the repository, run
 `pub global run mono_repo presubmit`.
 
+### Versioning
+
+You will also need to potentially update the pubspec.yaml and/or CHANGELOG.md of
+any package you are updating. If the current version is not a `-dev` version
+then you should update it and add a new header to the changelog. If you have no
+publicly facing change to list, it is OK for there to be no changes listed.
+
+We follow pretty strict semantic versioning, feel free to ask on the PR if you
+are unsure about what version number you should choose (or do your best, and a
+code reviewers will bring it up if it is incorrect).
+
 ### File headers
 
 All files in the project must start with the following header.
 
-    // Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+    // Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
     // for details. All rights reserved. Use of this source code is governed by a
     // BSD-style license that can be found in the LICENSE file.
 
+### Publishing
+
+Publishing is done by package owners creating a tag of the form
+`<package>-v<version>`, either manually or through the github release ui
+(preferred). The pubspec and changelog must already be updated to the desired
+release version in the master branch for this process to work.
+
 ### The small print
 
 Contributions made by corporations are covered by a different agreement than the
diff --git a/README.md b/README.md
deleted file mode 120000
index 789f748..0000000
--- a/README.md
+++ /dev/null
@@ -1 +0,0 @@
-pkgs/test/README.md
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7091bd9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+[![Dart CI](https://github.com/dart-lang/test/actions/workflows/dart.yml/badge.svg)](https://github.com/dart-lang/test/actions/workflows/dart.yml)
+[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/dart-lang/test/badge)](https://deps.dev/project/github/dart-lang%2Ftest)
+
+## What's here?
+
+Welcome! [package:test](pkgs/test/) is the standard testing library for Dart and
+Flutter. If you have questions about Dart testing, please see the docs for
+[package:test](pkgs/test/). `package:test_api` and `package:test_core`
+are implementation details and generally not user-facing.
+
+[package:checks](pkgs/checks/) is a relatively new library for expressing test
+expectations. It's a more modern version of `package:matcher` and features a
+literate API.
+
+## Packages
+
+| Package | Description | Version |
+|---|---|---|
+| [checks](pkgs/checks/) | A framework for checking values against expectations and building custom expectations. | [![pub package](https://img.shields.io/pub/v/checks.svg)](https://pub.dev/packages/checks) |
+| [test](pkgs/test/) | A full featured library for writing and running Dart tests across platforms. | [![pub package](https://img.shields.io/pub/v/test.svg)](https://pub.dev/packages/test) |
+| [test_api](pkgs/test_api/) |  | [![pub package](https://img.shields.io/pub/v/test_api.svg)](https://pub.dev/packages/test_api) |
+| [test_core](pkgs/test_core/) |  | [![pub package](https://img.shields.io/pub/v/test_core.svg)](https://pub.dev/packages/test_core) |
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 0f13fc8..9913045 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,13 +1,21 @@
-include: package:lints/recommended.yaml
+include: package:dart_flutter_team_lints/analysis_options.yaml
+
+
 analyzer:
   language:
     strict-casts: true
   errors:
     # There are a number of deprecated members used through this package
     deprecated_member_use_from_same_package: ignore
+
+    # Ignoring a number of lints from dart_flutter_team_lints – for now
+    avoid_catching_errors: ignore
+    avoid_dynamic_calls: ignore
+    lines_longer_than_80_chars: ignore
+    only_throw_errors: ignore
+    unawaited_futures: ignore
     unsafe_html: ignore
+
 linter:
   rules:
     - avoid_private_typedef_functions
-    - directives_ordering
-    - prefer_single_quotes
diff --git a/integration_tests/spawn_hybrid/pubspec.yaml b/integration_tests/spawn_hybrid/pubspec.yaml
index d5b58e1..de0efaa 100644
--- a/integration_tests/spawn_hybrid/pubspec.yaml
+++ b/integration_tests/spawn_hybrid/pubspec.yaml
@@ -1,7 +1,7 @@
 name: spawn_hybrid
 publish_to: none
 environment:
-  sdk: '>=2.18.0 <3.0.0'
+  sdk: ^3.0.0
 dependencies:
   async: ^2.9.0
   path: ^1.8.2
diff --git a/integration_tests/wasm/mono_pkg.yaml b/integration_tests/wasm/mono_pkg.yaml
index 9f50e7b..b09a8da 100644
--- a/integration_tests/wasm/mono_pkg.yaml
+++ b/integration_tests/wasm/mono_pkg.yaml
@@ -8,17 +8,17 @@
   - group:
     - format
     - analyze: --fatal-infos
-# TODO: restore after https://github.com/dart-lang/test/issues/1790
-# - unit_test:
-#   - group:
-#     - command:
-#       - pushd /tmp
-#       - wget https://dl.google.com/linux/direct/google-chrome-beta_current_amd64.deb
-#       - sudo dpkg -i google-chrome-beta_current_amd64.deb
-#       - popd
-#       - which google-chrome-beta
-#       os:
-#         - linux
-#     - test:
-#       os:
-#       - linux
+- unit_test:
+  - group:
+    - command:
+      - pushd /tmp
+      - wget https://dl.google.com/linux/direct/google-chrome-beta_current_amd64.deb
+      - sudo dpkg -i google-chrome-beta_current_amd64.deb
+      - popd
+      - which google-chrome-beta
+      os:
+        - linux
+    # The config here is a regression test for https://github.com/dart-lang/test/issues/2006
+    - test: --timeout=60s
+      os:
+      - linux
diff --git a/integration_tests/wasm/pubspec.yaml b/integration_tests/wasm/pubspec.yaml
index 37fed20..136c635 100644
--- a/integration_tests/wasm/pubspec.yaml
+++ b/integration_tests/wasm/pubspec.yaml
@@ -1,6 +1,7 @@
 name: wasm_tests
+publish_to: none
 environment:
-  sdk: ">=2.18.0 <3.0.0"
+  sdk: ^3.0.0
 dev_dependencies:
   test: any
 dependency_overrides:
diff --git a/integration_tests/wasm/test/hello_world_test.dart b/integration_tests/wasm/test/hello_world_test.dart
index 5d911a7..40d4a74 100644
--- a/integration_tests/wasm/test/hello_world_test.dart
+++ b/integration_tests/wasm/test/hello_world_test.dart
@@ -1,7 +1,10 @@
 // Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 @TestOn('wasm')
+// This retry is a regression test for https://github.com/dart-lang/test/issues/2006
+@Retry(2)
 import 'package:test/test.dart';
 
 void main() {
diff --git a/legacy_tests/nnbd_opted_in/mono_pkg.yaml b/legacy_tests/nnbd_opted_in/mono_pkg.yaml
deleted file mode 100644
index 682f76e..0000000
--- a/legacy_tests/nnbd_opted_in/mono_pkg.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-# See https://pub.dev/packages/mono_repo
-
-sdk:
-- pubspec
-
-stages:
-- analyze_and_format:
-  - group:
-    - format
-    - analyze: --fatal-infos
-    sdk:
-    - dev
-- unit_test:
-  - test: -p chrome,vm,node
-    os:
-    - linux
-    - windows
diff --git a/legacy_tests/nnbd_opted_in/pubspec.yaml b/legacy_tests/nnbd_opted_in/pubspec.yaml
deleted file mode 100644
index 61cadf7..0000000
--- a/legacy_tests/nnbd_opted_in/pubspec.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-name: nnbd_opted_in
-environment:
-  sdk: '>=2.18.0 <3.0.0'
-dev_dependencies:
-  lints: '>=1.0.0 <3.0.0'
-  test: any
-dependency_overrides:
-  test:
-    path: ../../pkgs/test
-  test_api:
-    path: ../../pkgs/test_api
-  test_core:
-    path: ../../pkgs/test_core
diff --git a/legacy_tests/nnbd_opted_in/test/common/is_opted_out.dart b/legacy_tests/nnbd_opted_in/test/common/is_opted_out.dart
deleted file mode 100644
index b661c9d..0000000
--- a/legacy_tests/nnbd_opted_in/test/common/is_opted_out.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-final bool isOptedOut = <int?>[] is List<int>;
diff --git a/legacy_tests/nnbd_opted_in/test/opted_in_test.dart b/legacy_tests/nnbd_opted_in/test/opted_in_test.dart
deleted file mode 100644
index 6f8eb9a..0000000
--- a/legacy_tests/nnbd_opted_in/test/opted_in_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test/test.dart';
-
-import 'common/is_opted_out.dart';
-
-void main() {
-  test('sound behavior', () async {
-    expect(isOptedOut, false);
-  });
-}
diff --git a/legacy_tests/nnbd_opted_in_with_optout/mono_pkg.yaml b/legacy_tests/nnbd_opted_in_with_optout/mono_pkg.yaml
deleted file mode 100644
index 5b5ac14..0000000
--- a/legacy_tests/nnbd_opted_in_with_optout/mono_pkg.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-# See https://pub.dev/packages/mono_repo
-
-sdk:
-- pubspec
-
-stages:
-- analyze_and_format:
-  - group:
-    - format
-    - analyze: --fatal-infos
-    sdk:
-    - pubspec
-- unit_test:
-  - test: -p chrome,vm,node
-    os:
-    - linux
-    - windows
diff --git a/legacy_tests/nnbd_opted_in_with_optout/pubspec.yaml b/legacy_tests/nnbd_opted_in_with_optout/pubspec.yaml
deleted file mode 100644
index 11517a6..0000000
--- a/legacy_tests/nnbd_opted_in_with_optout/pubspec.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-name: nnbd_opted_in_with_optout
-environment:
-  sdk: '>=2.18.0 <3.0.0'
-dev_dependencies:
-  lints: '>=1.0.0 <3.0.0'
-  test: any
-dependency_overrides:
-  test:
-    path: ../../pkgs/test
-  test_api:
-    path: ../../pkgs/test_api
-  test_core:
-    path: ../../pkgs/test_core
diff --git a/legacy_tests/nnbd_opted_in_with_optout/test/common/is_opted_out.dart b/legacy_tests/nnbd_opted_in_with_optout/test/common/is_opted_out.dart
deleted file mode 100644
index b661c9d..0000000
--- a/legacy_tests/nnbd_opted_in_with_optout/test/common/is_opted_out.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-final bool isOptedOut = <int?>[] is List<int>;
diff --git a/legacy_tests/nnbd_opted_in_with_optout/test/opted_out_test.dart b/legacy_tests/nnbd_opted_in_with_optout/test/opted_out_test.dart
deleted file mode 100644
index 291647f..0000000
--- a/legacy_tests/nnbd_opted_in_with_optout/test/opted_out_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.9
-
-import 'package:test/test.dart';
-
-import 'common/is_opted_out.dart';
-
-void main() {
-  test('unsound behavior', () async {
-    expect(isOptedOut, true);
-  });
-}
diff --git a/legacy_tests/nnbd_opted_out/mono_pkg.yaml b/legacy_tests/nnbd_opted_out/mono_pkg.yaml
deleted file mode 100644
index a8c8677..0000000
--- a/legacy_tests/nnbd_opted_out/mono_pkg.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-# See https://pub.dev/packages/mono_repo
-
-sdk:
-- 2.18.0
-
-stages:
-- analyze_and_format:
-  - group:
-    - format
-    - analyze: --fatal-infos
-    sdk:
-    - stable
-- unit_test:
-  - test: -p chrome,vm,node
-    os:
-    - linux
-    - windows
diff --git a/legacy_tests/nnbd_opted_out/pubspec.yaml b/legacy_tests/nnbd_opted_out/pubspec.yaml
deleted file mode 100644
index e73bf9d..0000000
--- a/legacy_tests/nnbd_opted_out/pubspec.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-name: nnbd_opted_out
-environment:
-  sdk: '>=2.11.0 <3.0.0'
-dev_dependencies:
-  lints: '>=1.0.0 <3.0.0'
-  test: any
-dependency_overrides:
-  test:
-    path: ../../pkgs/test
-  test_api:
-    path: ../../pkgs/test_api
-  test_core:
-    path: ../../pkgs/test_core
diff --git a/legacy_tests/nnbd_opted_out/test/common/is_opted_out.dart b/legacy_tests/nnbd_opted_out/test/common/is_opted_out.dart
deleted file mode 100644
index 7f4b628..0000000
--- a/legacy_tests/nnbd_opted_out/test/common/is_opted_out.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-//
-// @dart=2.12
-
-final bool isOptedOut = <int?>[] is List<int>;
diff --git a/legacy_tests/nnbd_opted_out/test/opted_in_test.dart b/legacy_tests/nnbd_opted_out/test/opted_in_test.dart
deleted file mode 100644
index 1d2e5b1..0000000
--- a/legacy_tests/nnbd_opted_out/test/opted_in_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-//
-// @dart=2.12
-
-import 'package:test/test.dart';
-
-import 'common/is_opted_out.dart';
-
-void main() {
-  test('is opted in to sound null safety', () {
-    expect(isOptedOut, isFalse);
-  });
-}
diff --git a/legacy_tests/nnbd_opted_out/test/opted_out_test.dart b/legacy_tests/nnbd_opted_out/test/opted_out_test.dart
deleted file mode 100644
index 1f1277d..0000000
--- a/legacy_tests/nnbd_opted_out/test/opted_out_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-//
-// @dart=2.9
-
-import 'package:test/test.dart';
-
-import 'common/is_opted_out.dart';
-
-void main() {
-  test('is opted out of sound null safety', () {
-    expect(isOptedOut, isTrue);
-  });
-}
diff --git a/legacy_tests/nnbd_opted_out/test/spawn_hybrid_code_test.dart b/legacy_tests/nnbd_opted_out/test/spawn_hybrid_code_test.dart
deleted file mode 100644
index 5a933d4..0000000
--- a/legacy_tests/nnbd_opted_out/test/spawn_hybrid_code_test.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test/test.dart';
-
-void main() {
-  group('spawnHybridCode', () {
-    test('uses the current package language version by default', () async {
-      final channel = spawnHybridCode(_hybridMain);
-      expect(await channel.stream.single, equals(true));
-    });
-
-    test('can set the language version with a marker', () async {
-      final channel = spawnHybridCode('// @dart=2.12\n$_hybridMain');
-      expect(await channel.stream.single, equals(false));
-    });
-  });
-}
-
-const _hybridMain = '''
-final isOptedOut = <int?>[] is List<int>;
-
-void hybridMain(dynamic channel) async {
-  channel.sink.add(isOptedOut);
-  channel.sink.close();
-}
-''';
diff --git a/legacy_tests/spawn_hybrid_with_optout/mono_pkg.yaml b/legacy_tests/spawn_hybrid_with_optout/mono_pkg.yaml
deleted file mode 100644
index 4ea5861..0000000
--- a/legacy_tests/spawn_hybrid_with_optout/mono_pkg.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-# See https://pub.dev/packages/mono_repo
-
-sdk:
-- pubspec
-
-stages:
-- analyze_and_format:
-  - group:
-    - format
-    - analyze: --fatal-infos
-    sdk:
-    - stable
-- unit_test:
-  - test: -p chrome,vm,node
-    os:
-    - linux
-    - windows
diff --git a/legacy_tests/spawn_hybrid_with_optout/pubspec.yaml b/legacy_tests/spawn_hybrid_with_optout/pubspec.yaml
deleted file mode 100644
index d02bf9f..0000000
--- a/legacy_tests/spawn_hybrid_with_optout/pubspec.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-name: spawn_hybrid_with_optout
-publish_to: none
-environment:
-  sdk: '>=2.18.0 <3.0.0'
-dev_dependencies:
-  lints: '>=1.0.0 <3.0.0'
-  test: any
-dependency_overrides:
-  test:
-    path: ../../pkgs/test
-  test_api:
-    path: ../../pkgs/test_api
-  test_core:
-    path: ../../pkgs/test_core
diff --git a/legacy_tests/spawn_hybrid_with_optout/test/hybrid_test.dart b/legacy_tests/spawn_hybrid_with_optout/test/hybrid_test.dart
deleted file mode 100644
index 5e2ff41..0000000
--- a/legacy_tests/spawn_hybrid_with_optout/test/hybrid_test.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test/test.dart';
-
-void main() {
-  group('spawnHybridCode()', () {
-    test('can opt out of null safety', () async {
-      expect(spawnHybridCode('''
-        // @dart=2.9
-        import "package:stream_channel/stream_channel.dart";
-
-        // Would cause an error in null safety mode.
-        int x;
-
-        void hybridMain(StreamChannel channel) {
-          channel.sink..add(1)..add(2)..add(3)..close();
-        }
-      ''').stream.toList(), completion(equals([1, 2, 3])));
-    });
-
-    test('opts in to null safety by default', () async {
-      expect(spawnHybridCode('''
-        import "package:stream_channel/stream_channel.dart";
-
-        // Use some null safety syntax
-        int? x;
-
-        void hybridMain(StreamChannel channel) {
-          channel.sink..add(1)..add(2)..add(3)..close();
-        }
-      ''').stream.toList(), completion(equals([1, 2, 3])));
-    });
-  });
-}
diff --git a/legacy_tests/unit_tests/mono_repo.yaml b/legacy_tests/unit_tests/mono_repo.yaml
deleted file mode 100644
index 4ea5861..0000000
--- a/legacy_tests/unit_tests/mono_repo.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-# See https://pub.dev/packages/mono_repo
-
-sdk:
-- pubspec
-
-stages:
-- analyze_and_format:
-  - group:
-    - format
-    - analyze: --fatal-infos
-    sdk:
-    - stable
-- unit_test:
-  - test: -p chrome,vm,node
-    os:
-    - linux
-    - windows
diff --git a/legacy_tests/unit_tests/pubspec.yaml b/legacy_tests/unit_tests/pubspec.yaml
deleted file mode 100644
index 4703f1e..0000000
--- a/legacy_tests/unit_tests/pubspec.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: legacy_unit_tests
-publish_to: none
-environment:
-  sdk: '>=2.18.0 <3.0.0'
-dev_dependencies:
-  lints: '>=1.0.0 <3.0.0'
-  package_config: ^2.0.0
-  path: ^1.8.0
-  test: any
-  test_descriptor: ^2.0.0
-  test_process: ^2.0.0
-dependency_overrides:
-  test:
-    path: ../../pkgs/test
-  test_api:
-    path: ../../pkgs/test_api
-  test_core:
-    path: ../../pkgs/test_core
diff --git a/legacy_tests/unit_tests/test/io.dart b/legacy_tests/unit_tests/test/io.dart
deleted file mode 100644
index b86b4c7..0000000
--- a/legacy_tests/unit_tests/test/io.dart
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. 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:io';
-import 'dart:isolate';
-
-import 'package:path/path.dart' as p;
-import 'package:test/test.dart';
-import 'package:test_descriptor/test_descriptor.dart' as d;
-import 'package:test_process/test_process.dart';
-
-/// The path to the root directory of the `test` package.
-final Future<String> packageDir =
-    Isolate.resolvePackageUri(Uri(scheme: 'package', path: 'test/'))
-        .then((uri) {
-  var dir = p.dirname(uri!.path);
-  // If it starts with a `/C:` or other drive letter, remove the leading `/`.
-  if (dir[0] == '/' && dir[2] == ':') dir = dir.substring(1);
-  return dir;
-});
-
-/// The path to the `pub` executable in the current Dart SDK.
-final _pubPath = p.absolute(p.join(p.dirname(Platform.resolvedExecutable),
-    Platform.isWindows ? 'pub.bat' : 'pub'));
-
-/// The platform-specific message emitted when a nonexistent file is loaded.
-final String noSuchFileMessage = Platform.isWindows
-    ? 'The system cannot find the file specified.'
-    : 'No such file or directory';
-
-/// A regular expression that matches the output of "pub serve".
-final _servingRegExp =
-    RegExp(r'^Serving myapp [a-z]+ on http://localhost:(\d+)$');
-
-/// An operating system name that's different than the current operating system.
-final otherOS = Platform.isWindows ? 'mac-os' : 'windows';
-
-/// The port of a pub serve instance run via [runPubServe].
-///
-/// This is only set after [runPubServe] is called.
-int get pubServePort => _pubServePort!;
-int? _pubServePort;
-
-/// Expects that the entire stdout stream of [test] equals [expected].
-void expectStdoutEquals(TestProcess test, String expected) =>
-    _expectStreamEquals(test.stdoutStream(), expected);
-
-/// Expects that the entire stderr stream of [test] equals [expected].
-void expectStderrEquals(TestProcess test, String expected) =>
-    _expectStreamEquals(test.stderrStream(), expected);
-
-/// Expects that the entirety of the line stream [stream] equals [expected].
-void _expectStreamEquals(Stream<String> stream, String expected) {
-  expect((() async {
-    var lines = await stream.toList();
-    expect(lines.join('\n').trim(), equals(expected.trim()));
-  })(), completes);
-}
-
-/// Returns a [StreamMatcher] that asserts that the stream emits strings
-/// containing each string in [strings] in order.
-///
-/// This expects each string in [strings] to match a different string in the
-/// stream.
-StreamMatcher containsInOrder(Iterable<String> strings) =>
-    emitsInOrder(strings.map((string) => emitsThrough(contains(string))));
-
-/// Lazily compile the test package to kernel and re-use that, initialized with
-/// [precompileTestExecutable].
-String? _testExecutablePath;
-
-/// Must be invoked before any call to [runTests], should be invoked in a top
-/// level `setUpAll` for best caching results.
-Future<void> precompileTestExecutable() async {
-  if (_testExecutablePath != null) {
-    throw StateError('Test executable already precompiled');
-  }
-  var tmpDirectory = await Directory.systemTemp.createTemp('test');
-  var precompiledPath = p.join(tmpDirectory.path, 'test_runner.dill');
-  var result = await Process.run(Platform.executable, [
-    'compile',
-    'kernel',
-    p.url.join(await packageDir, 'bin', 'test.dart'),
-    '-o',
-    precompiledPath,
-  ]);
-  if (result.exitCode != 0) {
-    throw StateError(
-        'Failed to compile test runner:\n${result.stdout}\n${result.stderr}');
-  }
-
-  addTearDown(() async {
-    await tmpDirectory.delete(recursive: true);
-  });
-  _testExecutablePath = precompiledPath;
-}
-
-/// Runs the test executable with the package root set properly.
-///
-/// You must invoke [precompileTestExecutable] before invoking this function.
-Future<TestProcess> runTest(Iterable<String> args,
-    {String? reporter,
-    String? fileReporter,
-    int? concurrency,
-    Map<String, String>? environment,
-    bool forwardStdio = false,
-    String? packageConfig,
-    Iterable<String>? vmArgs}) async {
-  concurrency ??= 1;
-  var testExecutablePath = _testExecutablePath;
-  if (testExecutablePath == null) {
-    throw StateError(
-        'You must call `precompileTestExecutable` before calling `runTest`');
-  }
-
-  var allArgs = [
-    ...?vmArgs,
-    testExecutablePath,
-    '--concurrency=$concurrency',
-    if (reporter != null) '--reporter=$reporter',
-    if (fileReporter != null) '--file-reporter=$fileReporter',
-    ...args,
-  ];
-
-  environment ??= {};
-  environment.putIfAbsent('_DART_TEST_TESTING', () => 'true');
-
-  return await runDart(allArgs,
-      environment: environment,
-      description: 'dart bin/test.dart',
-      forwardStdio: forwardStdio,
-      packageConfig: packageConfig);
-}
-
-/// Runs Dart.
-///
-/// If [packageConfig] is provided then that is passed for the `--packages`
-/// arg, otherwise the current isolate config is passed.
-Future<TestProcess> runDart(Iterable<String> args,
-    {Map<String, String>? environment,
-    String? description,
-    bool forwardStdio = false,
-    String? packageConfig}) async {
-  var allArgs = <String>[
-    ...Platform.executableArguments.where((arg) =>
-        !arg.startsWith('--package-root=') && !arg.startsWith('--packages=')),
-    '--packages=${packageConfig ?? await Isolate.packageConfig}',
-    ...args
-  ];
-
-  return await TestProcess.start(
-      p.absolute(Platform.resolvedExecutable), allArgs,
-      workingDirectory: d.sandbox,
-      environment: environment,
-      description: description,
-      forwardStdio: forwardStdio);
-}
-
-/// Runs Pub.
-Future<TestProcess> runPub(Iterable<String> args,
-    {Map<String, String>? environment}) {
-  return TestProcess.start(_pubPath, args,
-      workingDirectory: d.sandbox,
-      environment: environment,
-      description: 'pub ${args.first}');
-}
-
-/// Runs "pub serve".
-///
-/// This returns assigns [_pubServePort] to a future that will complete to the
-/// port of the "pub serve" instance.
-Future<TestProcess> runPubServe(
-    {Iterable<String>? args,
-    String? workingDirectory,
-    Map<String, String>? environment}) async {
-  var allArgs = ['serve', '--port', '0'];
-  if (args != null) allArgs.addAll(args);
-
-  var pub = await runPub(allArgs, environment: environment);
-
-  Match? match;
-  while (match == null) {
-    match = _servingRegExp.firstMatch(await pub.stdout.next);
-  }
-  _pubServePort = int.parse(match[1]!);
-
-  return pub;
-}
diff --git a/legacy_tests/unit_tests/test/runner_test.dart b/legacy_tests/unit_tests/test/runner_test.dart
deleted file mode 100644
index 5f67759..0000000
--- a/legacy_tests/unit_tests/test/runner_test.dart
+++ /dev/null
@@ -1,118 +0,0 @@
-import 'dart:convert';
-import 'dart:isolate';
-
-import 'package:package_config/package_config.dart';
-import 'package:path/path.dart' as p;
-import 'package:test/test.dart';
-import 'package:test_descriptor/test_descriptor.dart' as d;
-
-import 'io.dart';
-
-void main() {
-  setUpAll(precompileTestExecutable);
-
-  group('nnbd', () {
-    final testContents = '''
-import 'package:test/test.dart';
-import 'opted_out.dart';
-
-void main() {
-  test("success", () {
-    expect(foo, true);
-  });
-}''';
-
-    setUp(() async {
-      await d.file('opted_out.dart', '''
-// @dart=2.8
-final foo = true;''').create();
-    });
-
-    test('sound null safety is enabled if the entrypoint opts in explicitly',
-        () async {
-      await d.file('test.dart', '''
-// @dart=2.12
-$testContents
-''').create();
-      var test = await runTest(['test.dart']);
-
-      expect(
-          test.stdout,
-          emitsThrough(contains(
-              'Error: A library can\'t opt out of null safety by default, '
-              'when using sound null safety.')));
-      await test.shouldExit(1);
-    });
-
-    test('sound null safety is disabled if the entrypoint opts out explicitly',
-        () async {
-      await d.file('test.dart', '''
-// @dart=2.8
-$testContents''').create();
-      var test = await runTest(['test.dart']);
-
-      expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
-      await test.shouldExit(0);
-    });
-
-    group('defaults', () {
-      late PackageConfig currentPackageConfig;
-
-      setUpAll(() async {
-        currentPackageConfig =
-            await loadPackageConfigUri((await Isolate.packageConfig)!);
-      });
-
-      setUp(() async {
-        await d.file('test.dart', testContents).create();
-      });
-
-      test('sound null safety is enabled if the package is opted in', () async {
-        var newPackageConfig = PackageConfig([
-          ...currentPackageConfig.packages,
-          Package('example', Uri.file('${d.sandbox}/'),
-              languageVersion: LanguageVersion(2, 12),
-              // TODO: https://github.com/dart-lang/package_config/issues/81
-              packageUriRoot: Uri.file('${d.sandbox}/')),
-        ]);
-
-        await d
-            .file('package_config.json',
-                jsonEncode(PackageConfig.toJson(newPackageConfig)))
-            .create();
-
-        var test = await runTest(['test.dart'],
-            packageConfig: p.join(d.sandbox, 'package_config.json'));
-
-        expect(
-            test.stdout,
-            emitsThrough(contains(
-                'Error: A library can\'t opt out of null safety by default, '
-                'when using sound null safety.')));
-        await test.shouldExit(1);
-      });
-
-      test('sound null safety is disabled if the package is opted out',
-          () async {
-        var newPackageConfig = PackageConfig([
-          ...currentPackageConfig.packages,
-          Package('example', Uri.file('${d.sandbox}/'),
-              languageVersion: LanguageVersion(2, 8),
-              // TODO: https://github.com/dart-lang/package_config/issues/81
-              packageUriRoot: Uri.file('${d.sandbox}/')),
-        ]);
-
-        await d
-            .file('package_config.json',
-                jsonEncode(PackageConfig.toJson(newPackageConfig)))
-            .create();
-
-        var test = await runTest(['test.dart'],
-            packageConfig: p.join(d.sandbox, 'package_config.json'));
-
-        expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
-        await test.shouldExit(0);
-      });
-    });
-  });
-}
diff --git a/pkgs/checks/CHANGELOG.md b/pkgs/checks/CHANGELOG.md
index b38ba42..8f6105c 100644
--- a/pkgs/checks/CHANGELOG.md
+++ b/pkgs/checks/CHANGELOG.md
@@ -1,9 +1,42 @@
-# 0.1.1-dev
+## 0.3.0-wip
 
+-   **Breaking Changes**
+    -   Remove the `Condition` class and the `it()` utility. Replace calls to
+        `(it()..someExpectation())` with `((it) => it.someExpectation())`.
+-   Add class modifiers to restrict extension of implementation classes.
+
+## 0.2.2
+
+-   Return the first failure from `softCheck` and `softCheckAsync` as
+    documented, instead of the last failure when there are multiple failures.
+-   Add example `because` usage and mention the "reason" name in the migration
+    guide.
+-   Add `ComparableChecks` with comparison expectations for subject types that
+    implement `Comparable`.
+
+## 0.2.1
+
+-   Add a link to file issues with feedback in the README.
+
+## 0.2.0
+
+-   **Breaking Changes**
+    -   `checkThat` renamed to `check`.
+    -   `nest` and `nestAsync` take `Iterable<String> Function()` arguments for
+        `label` instead of `String`.
+    -   Async expectation extensions `completes`, `throws`, `emits`, and
+        `emitsError` no longer return a `Future<Subject>`. Instead they take an
+        optional `Condition` argument which can check expectations that would
+        have been checked on the returned subject.
+    -   `nestAsync` no longer returns a `Subject`, callers must pass the
+        followup `Condition` to the nullable argument.
+    -   Remove the `which` extension on `Future<Subject>`.
+    -   `matches` renamed to `matchesPattern` and now accepts a `Pattern`
+        argument, instead of limiting to `RegExp`.
 -   Added an example.
 -   Include a stack trace in the failure description for unexpected errors from
     Futures or Streams.
 
-# 0.1.0
+## 0.1.0
 
 -   Initial release.
diff --git a/pkgs/checks/README.md b/pkgs/checks/README.md
index 1c06f68..5415f11 100644
--- a/pkgs/checks/README.md
+++ b/pkgs/checks/README.md
@@ -1,80 +1,176 @@
-# Checking expectations with `checks`
+[![pub package](https://img.shields.io/pub/v/checks.svg)](https://pub.dev/packages/checks)
+[![package publisher](https://img.shields.io/pub/publisher/checks.svg)](https://pub.dev/packages/checks/publisher)
 
-Expectations start with `checkThat`. This utility returns a `Subject`, and
+`package:checks` is a library for expressing test expectations and it features
+a literate API.
+
+## package:checks preview
+
+`package:checks` is in preview; to provide feedback on the API, please file
+[an issue][] with questions, suggestions, feature requests, or general
+feedback.
+
+For documentation about migrating from `package:matcher` to `checks`, see the
+[migration guide][].
+
+[an issue]:https://github.com/dart-lang/test/issues/new?labels=package%3Achecks&template=03_checks_feedback.md
+[migration guide]:https://github.com/dart-lang/test/blob/master/pkgs/checks/doc/migrating_from_matcher.md
+
+## Quickstart
+
+1. Add a `dev_dependency` on `checks: ^0.2.0`.
+
+1. Add an import for `package:checks/checks.dart`.
+
+1. Use `checks` in your test code:
+
+```dart
+void main() {
+  test('sample test', () {
+    // test code here
+    ...
+
+    check(actual).equals(expected);
+    check(someList).isNotEmpty();
+    check(someObject).isA<Map>();
+    check(someString)..startsWith('a')..endsWith('z')..contains('lmno');
+  });
+}
+```
+
+## Checking expectations with `checks`
+
+Expectations start with `check`. This utility returns a `Subject`, and
 expectations can be checked against the subject. Expectations are defined as
 extension methods, and different expectations will be available for subjects
 with different value types.
 
 ```dart
-checkThat(someValue).equals(expectedValue);
-checkThat(someList).deepEquals(expectedList);
-checkThat(someString).contains('expected pattern');
+check(someValue).equals(expectedValue);
+check(someList).deepEquals(expectedList);
+check(someString).contains('expected pattern');
 ```
 
+If a failure may not have enough context about the actual or expected values
+from the expectation calls alone, add a "Reason" in the failure message by
+passing a `because:` argument to `check()`.
+
+```dart
+check(
+  because: 'log lines must start with the severity',
+  logLines,
+).every((l) => l
+  ..anyOf([
+    (l) => l.startsWith('ERROR'),
+    (l) => l.startsWith('WARNING'),
+    (l) => l.startsWith('INFO'),
+  ]));
+```
+
+
+### Composing expectations
+
+
 Multiple expectations can be checked against the same value using cascade
 syntax. When multiple expectations are checked against a single value, a failure
 will included descriptions of the expectations that already passed.
 
 ```dart
-checkThat(someString)
+check(someString)
   ..startsWith('a')
   ..endsWith('z')
   ..contains('lmno');
 ```
 
-Some expectations return a `Subject` for another value derived from the original
-value - for instance reading a field or awaiting the result of a Future.
+Some nested checks may be not be possible to write with cascade syntax.
+There is a `which` utility for this use case which takes a `Condition`.
 
 ```dart
-checkThat(someString).length.equals(expectedLength);
-(await checkThat(someFuture).completes()).equals(expectedCompletion);
+check(someString)
+  ..startsWith('a')
+  // A cascade would not be possible on `length`
+  ..length.which((l) => l
+    ..isGreatherThan(10)
+    ..isLessThan(100));
 ```
 
-Fields can be extracted from objects for checking further properties with the
-`has` utility.
+
+Some expectations return a `Subject` for another value derived from the original
+value, such as the `length` extension.
 
 ```dart
-checkThat(someValue)
+check(someString).length.equals(expectedLength);
+```
+
+Fields or derived values can be extracted from objects for checking further
+properties with the `has` utility.
+
+```dart
+check(someValue)
   .has((value) => value.property, 'property')
   .equals(expectedPropertyValue);
 ```
 
+### Passing a set of expectations as an argument
+
 Some expectations take arguments which are themselves expectations to apply to
-other values. These expectations take `Condition` arguments, which check
-expectations when they are applied to a `Subject`. The `ConditionSubject`
-utility acts as both a condition and a subject. Any expectations checked on the
-value as a subject will be recorded and replayed when it is applied as a
-condition. The `it()` utility returns a `ConditionSubject`.
+other values. These expectations take `Condition` arguments which have the
+signature void Function(Subject)`. The conditions check expectations when they
+are called with a `Subject` argument.
 
 ```dart
-checkThat(someList).any(it()..isGreaterThan(0));
+check(someList).any((e) => e.isGreaterThan(0));
 ```
 
-Some complicated checks may be difficult to write with parenthesized awaited
-expressions, or impossible to write with cascade syntax. There are `which`
-utilities for both use cases which take a `Condition`.
+### Checking asynchronous expectations
+
+Expectation extension methods checking asynchronous behavior return a `Future`.
+The future should typically be awaited within the test body, however
+asynchronous expectations will also ensure that the test is not considered
+complete before the expectation is complete.
+Expectations with no concrete end conditions, such as an expectation that a
+future never completes, cannot be awaited and may cause a failure after the test
+has already appeared to complete.
+
+Asynchronous expectations do not return a `Subject`. When an expectation
+extracts a derived value further expectations can be checked by passing a
+`Condition`.
 
 ```dart
-checkThat(someString)
-  ..startsWith('a')
-  // A cascade would not be possible on `length`
-  ..length.which(it()
-    ..isGreatherThan(10)
-    ..isLessThan(100));
-
-await checkThat(someFuture)
-    .completes()
-    .which(equals(expectedCompletion));
+await check(someFuture).completes((r) => r.isGreaterThan(0));
 ```
 
-# Writing custom expectations
+Subjects for `Stream` instances must first be wrapped into a `StreamQueue` to
+allow multiple expectations to test against the stream from the same state.
+The `withQueue` extension can be used when a given stream instance only needs to
+be checked once, or if it is a broadcast stream, but if single subscription
+stream needs to have multiple expectations checked separately it should be
+wrapped with a `StreamQueue`.
 
-Expectations are written as extension on `Subject` with specific generics. The
+```dart
+await check(someStream).withQueue.inOrder([
+  (s) => s.emits((e) => e.equals(1)),
+  (s) => s.emits((e) => e.equals(2)),
+  (s) => s.emits((e) => e.equals(3)),
+  (s) => s.isDone(),
+]);
+
+var someQueue = StreamQueue(someOtherStream);
+await check(someQueue).emits((e) => e.equals(1));
+// do something
+await check(someQueue).emits((e) => e.equals(2));
+// do something
+```
+
+
+## Writing custom expectations
+
+Expectations are written as extensions on `Subject` with specific generics. The
 library `package:checks/context.dart` gives access to a `context` getter on
 `Subject` which offers capabilities for defining expectations on the subject's
 value.
 
-The `Context` allows checking a expectation with `expect`, `expectAsync` and
+The `Context` allows checking an expectation with `expect`, `expectAsync` and
 `expectUnawaited`, or extracting a derived value for performing other checks
 with `nest` and `nestAsync`. Failures are reported by returning a `Rejection`,
 or an `Extracted.rejection`, extensions should avoid throwing exceptions.
@@ -82,9 +178,10 @@
 Descriptions of the clause checked by an expectations are passed through a
 separate callback from the predicate which checks the value. Nesting calls are
 made with a label directly. When there are no failures the clause callbacks are
-not called. When a `Condition` is described, the clause callbacks are called,
-but the predicate callbacks are not called. Conditions can be checked against
-values without throwing an exception using `softCheck` or `softCheckAsync`.
+not called. When a condition callback is described, the clause callbacks are
+called, but the predicate callbacks are not called. Conditions can be checked
+against values without throwing an exception using `softCheck` or
+`softCheckAsync`.
 
 ```dart
 extension CustomChecks on Subject<CustomType> {
@@ -96,7 +193,7 @@
   }
 
   Subject<Foo> get someDerivedValue =>
-      context.nest('has someDerivedValue', (actual) {
+      context.nest(() => ['has someDerivedValue'], (actual) {
         if (_cannotReadDerivedValue(actual)) {
           return Extracted.rejection(which: ['cannot read someDerivedValue']);
         }
@@ -108,42 +205,16 @@
 }
 ```
 
-# Trying Checks as a Preview
-
-1.  Add a `dev_dependency` on `checks: ^0.1.0`.
-
-1.  Replace the existing `package:test/test.dart` import with
-    `package:test/scaffolding.dart`.
-
-1.  Add an import to `package:checks/checks.dart`.
-
-1.  For an incremental migration within the test, add an import to
-    `package:test/expect.dart`. Remove it to surface errors in tests that still
-    need to be migrated, or keep it in so the tests work without being fully
-    migrated.
-
-1.  Migrate the test cases.
-
-# Migrating from Matchers
-
-Replace calls to `expect` with a call to `checkThat` passing the first argument.
-When a direct replacement is available, change the second argument from calling
-a function returning a Matcher, to calling the extension method on the
-`Subject`.
-
-When a non-matcher argument is used for the expected value, it would have been
-wrapped with `equals` automatically. See below, `.equals` may not always be the
-correct replacement in `package:checks`.
+Extensions may also compose existing expectations under a single name. When
+such expectations fail, the test output will refer to the individual
+expectations that were called.
 
 ```dart
-expect(actual, expected);
-checkThat(actual).equals(expected);
-// or maybe
-checkThat(actual).deepEquals(expected);
+extension ComposedChecks on Subject<Iterable> {
+  void hasLengthInRange(int min, int max) {
+    length
+      ..isGreaterThan(min)
+      ..isLessThan(max);
+  }
+}
 ```
-
-## Differences in behavior from matcher
-
--   The `equals` Matcher performed a deep equality check on collections.
-    `.equals()` expectation will only correspond to [operator ==] so some tests
-    may need to replace `.equals()` with `.deepEquals()`.
diff --git a/pkgs/checks/doc/migrating_from_matcher.md b/pkgs/checks/doc/migrating_from_matcher.md
new file mode 100644
index 0000000..82c4e3c
--- /dev/null
+++ b/pkgs/checks/doc/migrating_from_matcher.md
@@ -0,0 +1,198 @@
+## Migrating from package:matcher
+
+`package:checks` is currently in preview. Once this package reaches a stable
+version, it will be the recommended package by the Dart team to use for most
+tests.
+
+[`package:matcher`][matcher] is the legacy package with an API exported from
+`package:test/test.dart` and `package:test/expect.dart`. 
+
+**Do I have to migrate all at once?** No. `package:matcher` will be compatible
+with `package:checks`, and old tests can continue to use matchers. Test cases
+within the same file can use a mix of `expect` and `check`.
+
+**_Should_ I migrate all at once?** Probably not, it depends on your tolerance
+for having tests use a mix of APIs. As you add new tests, or need to make
+updates to existing tests, using `checks` will make testing easier. Tests which
+are stable and passing will not get significant benefits from a migration.
+
+**Do I need to migrate at all?** No. When `package:test`stops exporting
+these members it will be possible to add a dependency on `package:matcher` and
+continue to use them. `package:matcher` will continue to be available.
+
+**Why is the Dart team adding a second framework?** The `matcher` package has a
+design which is fundamentally incompatible with using static types to validate
+correct use. With an entirely new design, the static types in `checks` give
+confidence that the expectation is appropriate for the value, and can narrow
+autocomplete choices in the IDE for a better editing experience. The clean break
+from the legacy implementation and API also gives an opportunity to make small
+behavior and signature changes to align with modern Dart idioms.
+
+**Should I start using checks right away?** There is still a
+high potential for minor or major breaking changes during the preview window.
+Once this package is stable, yes! The experience of using `checks` improves on
+`matcher`. See some of the [improvements to look forward to in checks
+below](#improvements-you-can-expect).
+
+[matcher]: https://pub.dev/packages/matcher
+
+## Trying Checks as a Preview
+
+1.  Add a `dev_dependency` on `checks: ^0.2.0`.
+
+1.  Replace the existing `package:test/test.dart` import with
+    `package:test/scaffolding.dart`.
+
+1.  Add an import to `package:checks/checks.dart`.
+
+1.  For an incremental migration within the test, add an import to
+    `package:test/expect.dart`. Remove it to surface errors in tests that still
+    need to be migrated, or keep it in so the tests work without being fully
+    migrated.
+
+1.  Migrate the test cases.
+
+## Migrating from Matchers
+
+Replace calls to `expect` or `expectLater` with a call to `check` passing the
+first argument.
+When a direct replacement is available, change the second argument from calling
+a function returning a Matcher, to calling the relevant extension method on the
+`Subject`.
+
+Whenever you see a bare non-matcher value argument for `expected`, assume it
+should use the `equals` expectation, although take care when the subject is a
+collection.
+See below, `.equals` may not always be the correct replacement in
+`package:checks`.
+
+```dart
+expect(actual, expected);
+check(actual).equals(expected);
+// or maybe
+check(actualCollection).deepEquals(expected);
+
+await expectLater(actual, completes());
+await check(actual).completes();
+```
+
+If you use the `reason` argument to `expect`, rename it to `because`.
+
+```dart
+expect(actual, expectation(), reason: 'some explanation');
+check(because: 'some explanation', actual).expectation();
+```
+
+### Differences in behavior from matcher
+
+-   The `equals` Matcher performed a deep equality check on collections.
+    `.equals()` expectation will only correspond to [operator ==] so some tests
+    may need to replace `.equals()` with `.deepEquals()`.
+-   Streams must be explicitly wrapped into a `StreamQueue` before they can be
+    tested for behavior. Use `check(actualStream).withQueue`.
+-   `emitsAnyOf` is `Subject<StreamQueue>.anyOf`. `emitsInOrder` is `inOrder`.
+    The arguments are `FutureOr<void> Function(Subject<StreamQueue>)` and match
+    a behavior of the entire stream. In `matcher` the elements to expect could
+    have been a bare value to check for equality, a matcher for the emitted
+    value, or a matcher for the entire queue which would match multiple values.
+    Use `(s) => s.emits((e) => e.interestingCheck())` to check the emitted
+    elements.
+-   In `package:matcher` the [`matches` Matcher][matches] converted a `String`
+    argument into a `Regex`, so `matches(r'\d')` would match the value `'1'`.
+    This was potentially confusing, because even though `String` is a subtype of
+    `Pattern`, it wasn't used as a pattern directly.
+    With `matchesPattern` a `String` argument is used as a `Pattern` and
+    comparison uses [`String.allMatches`][allMatches].
+    For backwards compatibility change `matches(regexString)` to
+    `matchesPattern(RegExp(regexString))`.
+-   The `TypeMatcher.having` API is replace by the more general`.has`. While
+    `.having` could only be called on a `TypeMatcher` using `.isA`, `.has` works
+    on any `Subject`. `CoreChecks.has` takes 1 fewer arguments - instead of
+    taking the last argument, a `matcher` to apply to the field, it returns a
+    `Subject` for the field.
+
+[matches]:https://pub.dev/documentation/matcher/latest/matcher/Matcher/matches.html
+[allMatches]:https://api.dart.dev/stable/2.19.1/dart-core/Pattern/allMatches.html
+
+### Matchers with replacements under a different name
+
+-   `anyElement` -> `Subject<Iterable>.any`
+-   `everyElement` -> `Subject<Iterable>.every`
+-   `completion(Matcher)` -> `completes(conditionCallback)`
+-   `containsPair(key, value)` -> Use `Subject<Map>[key].equals(value)`
+-   `hasLength(expected)` -> `length.equals(expected)`
+-   `isNot(Matcher)` -> `not(conditionCallback)`
+-   `pairwiseCompare` -> `pairwiseComparesTo`
+-   `same` -> `identicalTo`
+-   `stringContainsInOrder` -> `Subject<String>.containsInOrder`
+
+### Members from `package:test/expect.dart` without a direct replacement
+
+-   `checks` does not ship with any type checking matchers for specific types.
+    Instead of, for example,  `isArgumentError` use `isA<ArgumentError>`, and
+    similary `throws<ArgumentError>` over `throwsArgumentError`.
+-   `anything`. When a condition callback is needed that should accept any
+    value, pass `(_) {}`.
+-   Specific numeric comparison - `isNegative`, `isPositive`, `isZero` and their
+    inverses. Use `isLessThan`, `isGreaterThan`, `isLessOrEqual`, and
+    `isGreaterOrEqual` with appropriate numeric arguments.
+-   Numeric range comparison, `inClosedOpenRange`, `inExclusiveRange`,
+    `inInclusiveRange`, `inOpenClosedRange`. Use cascades to chain a check for
+    both ends of the range onto the same subject.
+-   `containsOnce`: TODO add missing expectation
+-   `emitsInAnyOrder`: TODO add missing expectation
+-   `expectAsync` and `expectAsyncUntil`. Continue to import
+    `package:test/expect.dart` for these APIs.
+-   `isIn`: TODO add missing expectation
+-   `orderedEquals`: Use `deepEquals`. If the equality needs to specifically
+    *not* be deep equality (this is unusual, nested collections are unlikely to
+    have a meaningful equality), force using `operator ==` at the first level
+    with `.deepEquals(expected.map((e) => (Subject<Object?> s) => s.equals(e)))`;
+-   `prints`: TODO add missing expectation? Is this one worth replacing?
+-   `predicate`: TODO add missing expectation
+
+## Improvements you can expect
+
+Expectations are statically restricted to those which are appropriate for the
+type. So while the following is statically allowed with `matcher` but always
+fails at runtime, the expectation cannot be written at all with `checks`.
+
+```dart
+expect(1, contains(1)); // No static error, always fails
+check(1).contains(1); // Static error. The method 'contains' isn't defined
+```
+
+These static restrictions also improve the relevance of IDE autocomplete
+suggestions. While editing with the cursor at `_`, the suggestions provided
+in the `matcher` example can include _any_ top level element including matchers
+appropriate for other types of value, type names, and top level definitions from
+other packages. With the cursor following a `.` in the `checks` example the
+suggestions will only be expectations or utilities appropriate for the value
+type.
+
+```dart
+expect(actual, _ // many unrelated suggestions
+check(actual)._ // specific suggestions
+```
+
+Asynchronous matchers in `matcher` are a subtype of synchronous matchers, but do
+not satisfy the same behavior contract. Some APIs which use a matcher could not
+validate whether it would satisfy the behavior it needs, and it could result in
+a false success, false failure, or misleading errors. APIs which correctly use
+asynchronous matchers need to do a type check and change their interaction based
+on the runtime type. Asynchronous expectations in `checks` are refused at
+runtime when a synchronous answer is required. The error will help solve the
+specific misuse, instead of resulting in a confusing error, or worse a missed
+failure. The reason for the poor compatibility in `matcher` is due to some
+history of implementation - asynchronous matchers were written in `test`
+alongside `expect`, and synchronous matchers have no dependency on the
+asynchronous implementation.
+
+Asynchronous expectations always return a `Future`, and with the
+[`unawaited_futures` lint][unawaited lint] should more safely ensure that
+asynchronous expectation work is completed within the test body. With `matcher`
+it was up to the author to correctly use `await expecLater` for asynchronous
+cases, and `expect` for synchronous cases, and if `expect` was used with an
+asynchronous matcher the expectation could fail at any point.
+
+[unawaited lint]: https://dart.dev/lints/unawaited_futures
diff --git a/pkgs/checks/example/example.dart b/pkgs/checks/example/example.dart
index 621d42d..88bec0b 100644
--- a/pkgs/checks/example/example.dart
+++ b/pkgs/checks/example/example.dart
@@ -8,14 +8,17 @@
 void main() {
   test('sample test', () {
     final someValue = 5;
-    checkThat(someValue).equals(5);
+    check(someValue).equals(5);
 
     final someList = [1, 2, 3, 4, 5];
-    checkThat(someList).deepEquals([1, 2, 3, 4, 5]);
+    check(someList).deepEquals([1, 2, 3, 4, 5]);
 
     final someString = 'abcdefghijklmnopqrstuvwxyz';
 
-    checkThat(someString)
+    check(
+      because: 'it should contain the beginning, middle and end',
+      someString,
+    )
       ..startsWith('a')
       ..endsWith('z')
       ..contains('lmno');
diff --git a/pkgs/checks/lib/checks.dart b/pkgs/checks/lib/checks.dart
index 59cfb5f..a390e75 100644
--- a/pkgs/checks/lib/checks.dart
+++ b/pkgs/checks/lib/checks.dart
@@ -2,12 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-export 'src/checks.dart' show checkThat, Subject, Skip, it;
+export 'src/checks.dart'
+    show AsyncCondition, Condition, SkipExtension, Subject, check;
 export 'src/extensions/async.dart'
-    show ChainAsync, FutureChecks, StreamChecks, StreamQueueWrap;
+    show FutureChecks, StreamChecks, WithQueueExtension;
 export 'src/extensions/core.dart'
-    show BoolChecks, CoreChecks, NullabilityChecks, equals;
-export 'src/extensions/function.dart' show ThrowsCheck;
+    show BoolChecks, ComparableChecks, CoreChecks, NullableChecks, equals;
+export 'src/extensions/function.dart' show FunctionChecks;
 export 'src/extensions/iterable.dart' show IterableChecks;
 export 'src/extensions/map.dart' show MapChecks;
 export 'src/extensions/math.dart' show NumChecks;
diff --git a/pkgs/checks/lib/context.dart b/pkgs/checks/lib/context.dart
index c0a2311..cebba71 100644
--- a/pkgs/checks/lib/context.dart
+++ b/pkgs/checks/lib/context.dart
@@ -4,7 +4,7 @@
 
 export 'src/checks.dart'
     show
-        Subject,
+        AsyncCondition,
         CheckFailure,
         Condition,
         Context,
@@ -12,6 +12,7 @@
         Extracted,
         FailureDetail,
         Rejection,
+        Subject,
         describe,
         describeAsync,
         softCheck,
diff --git a/pkgs/checks/lib/src/checks.dart b/pkgs/checks/lib/src/checks.dart
index 3a43fd1..75107ba 100644
--- a/pkgs/checks/lib/src/checks.dart
+++ b/pkgs/checks/lib/src/checks.dart
@@ -2,13 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// TODO Add doc about how failure strings work.
 import 'dart:async';
 
 import 'package:meta/meta.dart' as meta;
 import 'package:test_api/hooks.dart';
 
 import 'describe.dart';
+import 'extensions/async.dart';
+import 'extensions/core.dart';
+import 'extensions/iterable.dart';
 
 /// A target for checking expectations against a value in a test.
 ///
@@ -16,15 +18,29 @@
 /// validated or rejected; or it may be a placeholder, in which case
 /// expectations describe what would be checked but cannot be rejected.
 ///
-/// Expectations are defined as extension methods specialized on the generic
-/// [T]. Expectations can use the [ContextExtension] to interact with the
-/// [Context] for this subject.
-class Subject<T> {
+/// Expectation methods are defined in extensions `on Subject`, specialized on
+/// the generic [T].
+/// Expectation extension methods can use the [ContextExtension] to interact
+/// with the [Context] for this subject.
+///
+/// Create a subject that throws an exception for missed expectations with the
+/// [check] function.
+final class Subject<T> {
   final Context<T> _context;
   Subject._(this._context);
 }
 
-extension Skip<T> on Subject<T> {
+/// A callback that synchronously checks expectations against a subject.
+///
+/// Asynchronous expectations should not be used within a `Condition` callback.
+typedef Condition<T> = void Function(Subject<T>);
+
+/// A callback that asynchronously checks expectations against a subject.
+///
+/// Any expectations may be used within an `AsyncCondition` callback.
+typedef AsyncCondition<T> = FutureOr<void> Function(Subject<T>);
+
+extension SkipExtension<T> on Subject<T> {
   /// Mark the currently running test as skipped and return a [Subject] that
   /// will ignore all expectations.
   ///
@@ -33,7 +49,7 @@
   /// failure.
   ///
   /// ```dart
-  /// checkThat(actual)
+  /// check(actual)
   ///     ..stillChecked()
   ///     ..skip('reason the expectation is temporarily not met').notChecked();
   /// ```
@@ -57,11 +73,10 @@
 /// messages.
 ///
 /// ```dart
-/// checkThat(actual).equals(expected);
+/// check(actual).equals(expected);
 /// ```
 @meta.useResult
-Subject<T> checkThat<T>(T value, {String? because}) =>
-    Subject._(_TestContext._root(
+Subject<T> check<T>(T value, {String? because}) => Subject._(_TestContext._root(
       value: _Present(value),
       // TODO - switch between "a" and "an"
       label: 'a $T',
@@ -94,12 +109,12 @@
   final subject = Subject<T>._(_TestContext._root(
     value: _Present(value),
     fail: (f) {
-      failure = f;
+      failure ??= f;
     },
     allowAsync: false,
     allowUnawaited: false,
   ));
-  condition.apply(subject);
+  condition(subject);
   return failure;
 }
 
@@ -112,17 +127,18 @@
 ///
 /// In contrast to [softCheck], asynchronous expectations are allowed in
 /// [condition].
-Future<CheckFailure?> softCheckAsync<T>(T value, Condition<T> condition) async {
+Future<CheckFailure?> softCheckAsync<T>(
+    T value, AsyncCondition<T> condition) async {
   CheckFailure? failure;
   final subject = Subject<T>._(_TestContext._root(
     value: _Present(value),
     fail: (f) {
-      failure = f;
+      failure ??= f;
     },
     allowAsync: true,
     allowUnawaited: false,
   ));
-  await condition.applyAsync(subject);
+  await condition(subject);
   return failure;
 }
 
@@ -146,7 +162,7 @@
     allowAsync: false,
     allowUnawaited: true,
   );
-  condition.apply(Subject._(context));
+  condition(Subject._(context));
   return context.detail(context).expected.skip(1);
 }
 
@@ -161,7 +177,7 @@
 ///
 /// In contrast to [describe], asynchronous expectations are allowed in
 /// [condition].
-Future<Iterable<String>> describeAsync<T>(Condition<T> condition) async {
+Future<Iterable<String>> describeAsync<T>(AsyncCondition<T> condition) async {
   final context = _TestContext<T>._root(
     value: _Absent(),
     fail: (_) {
@@ -170,58 +186,253 @@
     allowAsync: true,
     allowUnawaited: true,
   );
-  await condition.applyAsync(Subject._(context));
+  await condition(Subject._(context));
   return context.detail(context).expected.skip(1);
 }
 
-/// A set of expectations that are checked against the value when applied to a
-/// [Subject].
-abstract class Condition<T> {
-  void apply(Subject<T> subject);
-  Future<void> applyAsync(Subject<T> subject);
-}
-
-ConditionSubject<T> it<T>() => ConditionSubject._();
-
 extension ContextExtension<T> on Subject<T> {
   /// The expectations and nesting context for this subject.
   Context<T> get context => _context;
 }
 
-/// The expectation and nesting context already applied to a [Subject].
+/// The context for a [Subject] that allows asserting expectations and creating
+/// nested subjects.
 ///
-/// This is the surface of interaction for expectation extension method
-/// implementations.
+/// A [Subject] is the target for checking expectations in a test.
+/// Every subject has a [Context] which holds the "actual" value, tracks how the
+/// value was obtained, and can check expectations about the value.
 ///
-/// The `expect` and `expectAsync` can test the value and optionally reject it.
-/// The `nest` and `nestAsync` can test the value, and also extract some other
-/// property from it for further checking.
-abstract class Context<T> {
+/// The user focused APIs called within tests are expectation extension methods
+/// written in an extension `on Subject`, typically specialized to a specific
+/// generic.
+///
+/// Expectation extension methods will make a call to one of the APIs on the
+/// subject's [Context], and can perform one of two types of operations:
+///
+/// -   Expect something of the current value (such as [CoreChecks.equals] or
+///     [IterableChecks.contains]) by calling [expect], [expectAsync], or
+///     [expectUnawaited].
+/// -   Expect that a new subject can be extracted from the current value (such
+///     as [CoreChecks.has] or [FutureChecks.completes]) by calling [nest] or
+///     [nestAsync].
+///
+///
+/// Whichever type of operation, an expectation extension method provides two
+/// callbacks.
+/// The first callback is an `Iterable<String> Function()` returning a
+/// description of the expectation.
+/// The second callback always takes the actual value as an argument, and the
+/// specific signature varies by operation.
+///
+///
+/// In expectation extension methods calling [expect], [expectAync], or
+/// [expectUnawaited], the `predicate` callback can report a [Rejection] if the
+/// value fails to satisfy the expectation.
+/// The description will be passed in a "clause" callback.
+/// {@template clause_description}
+/// The clause callback returns a description of what is checked which stands
+/// on its own.
+/// For instance the `is equal to <1>` in:
+///
+/// ```
+/// Expected: a int that:
+///   is equal to <1>
+/// ```
+/// {@endtemplate}
+///
+///
+/// In expectation extension methods calling [nest] or [nestAsync], the
+/// `extract` callback can return a [Extracted.rejection] if the value fails to
+/// satisfy an expectation which disallows extracting the value, or an
+/// [Extracted.value] to become the value in a nested subject.
+/// The description will be passed in a "label" callback.
+/// {@template label_description}
+/// The label callback returns a description of the extracted subject as it
+/// relates to the original subject.
+/// For instance the `completes to a value` in:
+///
+/// ```
+/// Expected a Future<int> that:
+///   completes to a value that:
+///     is equal to <1>
+/// ```
+///
+/// A label should also be sensible when it is read as a clause.
+/// If no further expectations are checked on the extracted subject, or if the
+/// extraction is rejected, the "that:" is omitted in the output.
+///
+/// ```
+///   Expected a Future<int> that:
+///     completes to a value
+/// ```
+/// {@endtemplate}
+///
+///
+/// A rejection carries two descriptions, one description of the "actual" value
+/// that was tested, and an optional "which" with further details about how the
+/// result different from the expectation.
+/// If the "actual" argument is omitted it will be filled with a representation
+/// of the value passed to the expectation callback formatted with [literal].
+/// If an expectation extension method is written on a type of subject without a
+/// useful `toString()`, the rejection can provide a string representation to
+/// use instead.
+/// The "which" argument may be omitted if the reason is very obvious based on
+/// the clause and "actual" description, but most expectations should include a
+/// "which".
+///
+/// The behavior of a context following a rejection depends on the source of the
+/// [Subject].
+///
+/// When an expectation is rejected for a [check] subject, an exception is
+/// thrown to interrupt the test, so no further checks should happen. The
+/// failure message will include:
+/// -  An "Expected" section with descriptions of all the expectations that
+///    were checked, including the ones that passed, and the last one that
+///    failed.
+/// -  An "Actual" section, which may be the description directly from the
+///    [Rejection] if the failure was on the root subject, or may start with a
+///    partial version of the "Expected" description up to the label for the
+///    nesting subject that saw a failure, then the "actual" from the rejection.
+/// -  A "Which" description from the rejection, if it was included.
+///
+/// For example, if a failure happens on the root subject, the "actual" is taken
+/// directly from the rejection.
+///
+/// ```
+/// Expected: a Future<int> that:
+///   completes to a value
+/// Actual: a future that completes as an error
+/// Which: threw <UnimplementedError> at:
+/// <stack trace>
+/// ```
+///
+/// But if the failure happens on a nested subject, the actual starts with a
+/// description of the nesting or non-nesting expectations that succeeded, up
+/// to nesting point of the failure, then the "actual" and "which" from the
+/// rejection are indented to that level of nesting.
+///
+/// ```
+/// Expected: a Future<int> that:
+///   completes to a value that:
+///     equals <1>
+/// Actual: a Future<int> that:
+///   completes to a value that:
+///   Actual: <0>
+///   Which: are not equal
+/// ```
+///
+/// ```dart
+/// extension CustomChecks on Subject<CustomType> {
+///   void someExpectation() {
+///     context.expect(() => ['meets this expectation'], (actual) {
+///       if (_expectationIsMet(actual)) return null;
+///       return Rejection(which: ['does not meet this expectation']);
+///     });
+///   }
+///
+///   Subject<Foo> get someDerivedValue =>
+///       context.nest('has someDerivedValue', (actual) {
+///         if (_cannotReadDerivedValue(actual)) {
+///           return Extracted.rejection(which: ['cannot read someDerivedValue']);
+///         }
+///         return Extracted.value(_readDerivedValue(actual));
+///       });
+///
+///   // for field reads that will not get rejected, use `has`
+///   Subject<Bar> get someField => has((a) => a.someField, 'someField');
+/// }
+/// ```
+///
+/// When an expectation is rejected for a subject within a call to [softCheck]
+/// or [softCheckAsync] a [CheckFailure] will be returned with the rejection, as
+/// well as a [FailureDetail] which could be used to format the same failure
+/// message thrown by the [check] subject.
+///
+/// {@template callbacks_may_be_unused}
+/// The description of an expectation may never be shown to the user, so the
+/// callback may never be invoked.
+/// If all the conditions on a subject succeed, or if the failure detail for a
+/// failed [softCheck] is never read, the descriptions will be unused.
+/// String formatting for the descriptions should be performed in the callback,
+/// not ahead of time.
+///
+///
+/// The context for a subject may hold a real "actual" value to test against, or
+/// it may have a placeholder within a call to [describe].
+/// A context with a placeholder value will not invoke the callback to check
+/// expectations.
+///
+/// If both callbacks are invoked, the description callback will always be
+/// called strictly after the expectation callback is called.
+///
+/// Callbacks passed to a context should not throw.
+/// {@endtemplate}
+///
+///
+/// Some contexts disallow certain interactions.
+/// {@template async_limitations}
+/// Calls to [expectAsync] or [nestAsync] must not be performed by a condition
+/// callback passed to [softCheck] or [describe].
+/// Use [softCheckAsync] or [describeAsync] for any condition which checks async
+/// expectations.
+/// {@endtemplate}
+/// {@template unawaited_limitations}
+/// Calls to [expectUnawaited] may not be performed by a condition callback
+/// passed to [softCheck] or [softCheckAsync].
+/// {@endtemplate}
+///
+/// Expectation extension methods can access the context for the subject with
+/// the [ContextExtension].
+///
+/// {@template description_lines}
+/// Description callbacks return an `Iterable<String>` where each element is a
+/// line in the output. Individual elements should not contain newlines.
+/// Utilities such as [prefixFirst], [postfixLast], and [literal] may be useful
+/// to format values which are potentially multiline.
+/// {@endtemplate}
+abstract final class Context<T> {
   /// Expect that [predicate] will not return a [Rejection] for the checked
   /// value.
   ///
-  /// The property that is asserted by this expectation is described by
-  /// [clause]. Often this is a single statement like "equals <1>" or "is
-  /// greater than 10", but it may be multiple lines such as describing that an
-  /// Iterable contains an element meeting a complex expectation. If any element
-  /// in the returned iterable contains a newline it may cause problems with
-  /// indentation in the output.
+  /// {@macro clause_description}
+  ///
+  /// {@macro description_lines}
+  ///
+  /// {@macro callbacks_may_be_unused}
+  ///
+  /// ```dart
+  /// void someExpectation() {
+  ///   context.expect(() => ['meets this expectation'], (actual) {
+  ///     if (_expectationIsMet(actual)) return null;
+  ///     return Rejection(which: ['does not meet this expectation']);
+  ///   });
+  /// }
+  /// ```
   void expect(
       Iterable<String> Function() clause, Rejection? Function(T) predicate);
 
   /// Expect that [predicate] will not result in a [Rejection] for the checked
   /// value.
   ///
-  /// The property that is asserted by this expectation is described by
-  /// [clause]. Often this is a single statement like "equals <1>" or "is
-  /// greater than 10", but it may be multiple lines such as describing that an
-  /// Iterable contains an element meeting a complex expectation. If any element
-  /// in the returned iterable contains a newline it may cause problems with
-  /// indentation in the output.
+  /// {@macro clause_description}
   ///
-  /// Some context may disallow asynchronous expectations, for instance in
-  /// [softCheck] which must synchronously check the value. In those contexts
-  /// this method will throw.
+  /// {@macro description_lines}
+  ///
+  /// {@macro callbacks_may_be_unused}
+  ///
+  /// {@macro async_limitations}
+  ///
+  /// ```dart
+  /// extension CustomChecks on Subject<CustomType> {
+  ///   Future<void> someAsyncExpectation() async {
+  ///     await context.expectAsync(() => ['meets this async expectation'],
+  ///         (actual) async {
+  ///       if (await _expectationIsMet(actual)) return null;
+  ///       return Rejection(which: ['does not meet this async expectation']);
+  ///     });
+  ///   }
+  /// }
+  /// ```
   Future<void> expectAsync<R>(Iterable<String> Function() clause,
       FutureOr<Rejection?> Function(T) predicate);
 
@@ -237,10 +448,29 @@
   /// listening for the event, there is no way to complete a returned future and
   /// consider the check "complete".
   ///
-  /// May not be used from the context for a [Subject] created by [softCheck] or
-  /// [softCheckAsync]. The only useful effect of a late rejection is to throw a
-  /// [TestFailure] when used with a [checkThat] subject. Most conditions should
-  /// prefer to use [expect] or [expectAsync].
+  /// {@macro clause_description}
+  ///
+  /// {@macro description_lines}
+  ///
+  /// {@macro callbacks_may_be_unused}
+  ///
+  /// {@macro unawaited_limitations}
+  /// The only useful effect of a late rejection is to throw a [TestFailure]
+  /// when used with a [check] subject. Most conditions should prefer to use
+  /// [expect] or [expectAsync].
+  ///
+  /// ```dart
+  /// void someUnawaitableExpectation() async {
+  ///   await context.expectUnawaited(
+  ///       () => ['meets this unawaitable expectation'], (actual, reject) {
+  ///     final failureSignal = _completeIfFailed(actual);
+  ///     unawaited(failureSignal.then((_) {
+  ///       reject(Reject(
+  ///           which: ['unexpectedly failed this unawaited expectation']));
+  ///     }));
+  ///   });
+  /// }
+  /// ```
   void expectUnawaited(Iterable<String> Function() clause,
       void Function(T, void Function(Rejection)) predicate);
 
@@ -250,19 +480,38 @@
   /// [Extracted.rejection] describing the problem. Otherwise it should return
   /// an [Extracted.value].
   ///
-  /// The [label] will be used preceding "that:" in a description. Expectations
-  /// applied to the returned [Subject] will follow the label, indented by two
-  /// more spaces.
+  /// Subsequent expectations can be checked for the extracted value on the
+  /// returned [Subject].
   ///
-  /// If [atSameLevel] is true then [R] should be a subtype of [T], and a
-  /// returned [Extracted.value] should be the same instance as the passed
-  /// value, or an object which is is equivalent but has a type which is more
-  /// convenient to test. In this case expectations applied to the return
-  /// [Subject] will behave as if they were applied to the subject for this
-  /// context. The [label] will be used as if it were a single line "clause"
-  /// passed to [expect]. If the label is empty, the clause will be omitted. The
-  /// label should only be left empty if the value extraction cannot fail.
-  Subject<R> nest<R>(String label, Extracted<R> Function(T) extract,
+  /// {@macro label_description}
+  ///
+  /// If [atSameLevel] is true then the returned [Extracted.value] should hold
+  /// the same instance as the passed value, or an object which is is equivalent
+  /// but has a type that is more convenient to test.
+  /// In this case expectations applied to the returned [Subject] will behave as
+  /// if they were applied to the subject for this context.
+  /// The [label] will be used as if it were a "clause" argument passed to
+  /// [expect].
+  /// If the label returns an empty iterable, the clause will be omitted.
+  /// The label should only be left empty if the value extraction cannot be
+  /// rejected.
+  ///
+  /// {@macro description_lines}
+  ///
+  /// {@macro callbacks_may_be_unused}
+  ///
+  /// ```dart
+  /// Subject<Foo> get someDerivedValue =>
+  ///     context.nest(() => ['has someDerivedValue'], (actual) {
+  ///       if (_cannotReadDerivedValue(actual)) {
+  ///         return Extracted.rejection(
+  ///             which: ['cannot read someDerivedValue']);
+  ///       }
+  ///       return Extracted.value(_readDerivedValue(actual));
+  ///     });
+  /// ```
+  Subject<R> nest<R>(
+      Iterable<String> Function() label, Extracted<R> Function(T) extract,
       {bool atSameLevel = false});
 
   /// Extract an asynchronous property from the value for further checking.
@@ -271,21 +520,39 @@
   /// [Extracted.rejection] describing the problem. Otherwise it should return
   /// an [Extracted.value].
   ///
-  /// The [label] will be used preceding "that:" in a description. Expectations
-  /// applied to the returned [Subject] will follow the label, indented by two
-  /// more spaces.
+  /// In contrast to [nest], subsequent expectations need to be passed in
+  /// [nestedCondition] which will be applied to the subject for the extracted
+  /// value.
   ///
-  /// Some context may disallow asynchronous expectations, for instance in
-  /// [softCheck] which must synchronously check the value. In those contexts
-  /// this method will throw.
-  Future<Subject<R>> nestAsync<R>(
-      String label, FutureOr<Extracted<R>> Function(T) extract);
+  /// {@macro label_description}
+  ///
+  /// {@macro description_lines}
+  ///
+  /// {@macro callbacks_may_be_unused}
+  ///
+  /// {@macro async_limitations}
+  ///
+  /// ```dart
+  /// Future<void> someAsyncResult(
+  ///     [AsyncCondition<Result> resultCondition]) async {
+  ///   await context.nestAsync(() => ['has someAsyncResult'], (actual) async {
+  ///     if (await _asyncOperationFailed(actual)) {
+  ///       return Extracted.rejection(which: ['cannot read someAsyncResult']);
+  ///     }
+  ///     return Extracted.value(await _readAsyncResult(actual));
+  ///   }, resultCondition);
+  /// }
+  /// ```
+  Future<void> nestAsync<R>(
+      Iterable<String> Function() label,
+      FutureOr<Extracted<R>> Function(T) extract,
+      AsyncCondition<R>? nestedCondition);
 }
 
 /// A property extracted from a value being checked, or a rejection.
-class Extracted<T> {
-  final Rejection? rejection;
-  final T? value;
+final class Extracted<T> {
+  final Rejection? _rejection;
+  final T? _value;
 
   /// Creates a rejected extraction to indicate a failure trying to read the
   /// value.
@@ -294,25 +561,25 @@
   /// will be filled in with the [literal] representation of the value.
   Extracted.rejection(
       {Iterable<String> actual = const [], Iterable<String>? which})
-      : rejection = Rejection(actual: actual, which: which),
-        value = null;
-  Extracted.value(T this.value) : rejection = null;
+      : _rejection = Rejection(actual: actual, which: which),
+        _value = null;
+  Extracted.value(T this._value) : _rejection = null;
 
-  Extracted._(Rejection this.rejection) : value = null;
+  Extracted._(Rejection this._rejection) : _value = null;
 
   Extracted<R> _map<R>(R Function(T) transform) {
-    final rejection = this.rejection;
+    final rejection = _rejection;
     if (rejection != null) return Extracted._(rejection);
-    return Extracted.value(transform(value as T));
+    return Extracted.value(transform(_value as T));
   }
 
-  Extracted<T> _fillActual(Object? actual) => rejection == null ||
-          rejection!.actual.isNotEmpty
+  Extracted<T> _fillActual(Object? actual) => _rejection == null ||
+          _rejection!.actual.isNotEmpty
       ? this
-      : Extracted.rejection(actual: literal(actual), which: rejection!.which);
+      : Extracted.rejection(actual: literal(actual), which: _rejection!.which);
 }
 
-abstract class _Optional<T> {
+abstract interface class _Optional<T> {
   R? apply<R extends FutureOr<Rejection?>>(R Function(T) callback);
   Future<Extracted<_Optional<R>>> mapAsync<R>(
       FutureOr<Extracted<R>> Function(T) transform);
@@ -330,12 +597,12 @@
   Future<Extracted<_Present<R>>> mapAsync<R>(
       FutureOr<Extracted<R>> Function(T) transform) async {
     final transformed = await transform(value);
-    return transformed._map((v) => _Present(v));
+    return transformed._map(_Present.new);
   }
 
   @override
   Extracted<_Present<R>> map<R>(Extracted<R> Function(T) transform) =>
-      transform(value)._map((v) => _Present(v));
+      transform(value)._map(_Present.new);
 }
 
 class _Absent<T> implements _Optional<T> {
@@ -352,7 +619,7 @@
       Extracted.value(_Absent<R>());
 }
 
-class _TestContext<T> implements Context<T>, _ClauseDescription {
+final class _TestContext<T> implements Context<T>, _ClauseDescription {
   final _Optional<T> _value;
 
   /// A reference to find the root context which this context is nested under.
@@ -363,14 +630,37 @@
   final List<_ClauseDescription> _clauses;
   final List<_TestContext> _aliases;
 
-  // The "a value" in "a value that:".
-  final String _label;
-
   final void Function(CheckFailure) _fail;
 
   final bool _allowAsync;
   final bool _allowUnawaited;
 
+  /// A callback that returns a label for this context.
+  ///
+  /// If this context is the root the label should return a phrase like
+  /// "a List" in
+  ///
+  /// ```
+  /// Expected: a List that:
+  /// ```
+  ///
+  /// If this context is nested under another context the lable should return a
+  /// phrase like "completes to a value" in
+  ///
+  ///
+  /// ```
+  /// Expected: a Future<int> that:
+  ///   completes to a value that:
+  /// ```
+  ///
+  /// In cases where a nested context does not have any expectations checked on
+  /// it, the "that:" will be will be omitted.
+  final Iterable<String> Function() _label;
+
+  static Iterable<String> _emptyLabel() => const [];
+
+  /// Create a context appropriate for a subject which is not nested under any
+  /// other subject.
   _TestContext._root({
     required _Optional<T> value,
     required void Function(CheckFailure) fail,
@@ -378,7 +668,7 @@
     required bool allowUnawaited,
     String? label,
   })  : _value = value,
-        _label = label ?? '',
+        _label = (() => [label ?? '']),
         _fail = fail,
         _allowAsync = allowAsync,
         _allowUnawaited = allowUnawaited,
@@ -395,8 +685,11 @@
         _allowUnawaited = original._allowUnawaited,
         // Never read from an aliased context because they are never present in
         // `_clauses`.
-        _label = '';
+        _label = _emptyLabel;
 
+  /// Create a context nested under [parent].
+  ///
+  /// The [_label] callback should not return an empty iterable.
   _TestContext._child(this._value, this._label, _TestContext<dynamic> parent)
       : _parent = parent,
         _fail = parent._fail,
@@ -408,7 +701,7 @@
   @override
   void expect(
       Iterable<String> Function() clause, Rejection? Function(T) predicate) {
-    _clauses.add(_StringClause(clause));
+    _clauses.add(_ExpectationClause(clause));
     final rejection =
         _value.apply((actual) => predicate(actual)?._fillActual(actual));
     if (rejection != null) {
@@ -423,13 +716,16 @@
       throw StateError(
           'Async expectations cannot be used on a synchronous subject');
     }
-    _clauses.add(_StringClause(clause));
+    _clauses.add(_ExpectationClause(clause));
     final outstandingWork = TestHandle.current.markPending();
-    final rejection = await _value.apply(
-        (actual) async => (await predicate(actual))?._fillActual(actual));
-    outstandingWork.complete();
-    if (rejection == null) return;
-    _fail(_failure(rejection));
+    try {
+      final rejection = await _value.apply(
+          (actual) async => (await predicate(actual))?._fillActual(actual));
+      if (rejection == null) return;
+      _fail(_failure(rejection));
+    } finally {
+      outstandingWork.complete();
+    }
   }
 
   @override
@@ -438,27 +734,28 @@
     if (!_allowUnawaited) {
       throw StateError('Late expectations cannot be used for soft checks');
     }
-    _clauses.add(_StringClause(clause));
+    _clauses.add(_ExpectationClause(clause));
     _value.apply((actual) {
       predicate(actual, (r) => _fail(_failure(r._fillActual(actual))));
     });
   }
 
   @override
-  Subject<R> nest<R>(String label, Extracted<R> Function(T) extract,
+  Subject<R> nest<R>(
+      Iterable<String> Function() label, Extracted<R> Function(T) extract,
       {bool atSameLevel = false}) {
     final result = _value.map((actual) => extract(actual)._fillActual(actual));
-    final rejection = result.rejection;
+    final rejection = result._rejection;
     if (rejection != null) {
-      _clauses.add(_StringClause(() => [label]));
+      _clauses.add(_ExpectationClause(label));
       _fail(_failure(rejection));
     }
-    final value = result.value ?? _Absent<R>();
+    final value = result._value ?? _Absent<R>();
     final _TestContext<R> context;
     if (atSameLevel) {
       context = _TestContext._alias(this, value);
       _aliases.add(context);
-      if (label.isNotEmpty) _clauses.add(_StringClause(() => [label]));
+      _clauses.add(_ExpectationClause(label));
     } else {
       context = _TestContext._child(value, label, this);
       _clauses.add(context);
@@ -467,25 +764,30 @@
   }
 
   @override
-  Future<Subject<R>> nestAsync<R>(
-      String label, FutureOr<Extracted<R>> Function(T) extract) async {
+  Future<void> nestAsync<R>(
+      Iterable<String> Function() label,
+      FutureOr<Extracted<R>> Function(T) extract,
+      AsyncCondition<R>? nestedCondition) async {
     if (!_allowAsync) {
       throw StateError(
           'Async expectations cannot be used on a synchronous subject');
     }
     final outstandingWork = TestHandle.current.markPending();
-    final result = await _value.mapAsync(
-        (actual) async => (await extract(actual))._fillActual(actual));
-    outstandingWork.complete();
-    final rejection = result.rejection;
-    if (rejection != null) {
-      _clauses.add(_StringClause(() => [label]));
-      _fail(_failure(rejection));
+    try {
+      final result = await _value.mapAsync(
+          (actual) async => (await extract(actual))._fillActual(actual));
+      final rejection = result._rejection;
+      if (rejection != null) {
+        _clauses.add(_ExpectationClause(label));
+        _fail(_failure(rejection));
+      }
+      final value = result._value ?? _Absent<R>();
+      final context = _TestContext<R>._child(value, label, this);
+      _clauses.add(context);
+      await nestedCondition?.call(Subject<R>._(context));
+    } finally {
+      outstandingWork.complete();
     }
-    final value = result.value ?? _Absent<R>();
-    final context = _TestContext<R>._child(value, label, this);
-    _clauses.add(context);
-    return Subject._(context);
   }
 
   CheckFailure _failure(Rejection rejection) =>
@@ -508,9 +810,9 @@
     var successfulOverlap = 0;
     final expected = <String>[];
     if (_clauses.isEmpty) {
-      expected.add(_label);
+      expected.addAll(_label());
     } else {
-      expected.add('$_label that:');
+      expected.addAll(postfixLast(' that:', _label()));
       for (var clause in _clauses) {
         final details = clause.detail(failingContext);
         expected.addAll(indent(details.expected));
@@ -531,7 +833,7 @@
 }
 
 /// A context which never runs expectations and can never fail.
-class _SkippedContext<T> implements Context<T> {
+final class _SkippedContext<T> implements Context<T> {
   @override
   void expect(
       Iterable<String> Function() clause, Rejection? Function(T) predicate) {
@@ -551,32 +853,35 @@
   }
 
   @override
-  Subject<R> nest<R>(String label, Extracted<R> Function(T p1) extract,
+  Subject<R> nest<R>(
+      Iterable<String> Function() label, Extracted<R> Function(T p1) extract,
       {bool atSameLevel = false}) {
     return Subject._(_SkippedContext());
   }
 
   @override
-  Future<Subject<R>> nestAsync<R>(
-      String label, FutureOr<Extracted<R>> Function(T p1) extract) async {
-    return Subject._(_SkippedContext());
+  Future<void> nestAsync<R>(
+      Iterable<String> Function() label,
+      FutureOr<Extracted<R>> Function(T p1) extract,
+      AsyncCondition<R>? nestedCondition) async {
+    // no-op
   }
 }
 
-abstract class _ClauseDescription {
+abstract interface class _ClauseDescription {
   FailureDetail detail(_TestContext failingContext);
 }
 
-class _StringClause implements _ClauseDescription {
+class _ExpectationClause implements _ClauseDescription {
   final Iterable<String> Function() _expected;
-  _StringClause(this._expected);
+  _ExpectationClause(this._expected);
   @override
   FailureDetail detail(_TestContext failingContext) =>
       FailureDetail(_expected(), -1, -1);
 }
 
 /// The result an expectation that failed for a subject..
-class CheckFailure {
+final class CheckFailure {
   /// The specific rejected value within the overall subject that caused the
   /// failure.
   ///
@@ -597,10 +902,10 @@
 ///
 /// A subject may have some number of succeeding expectations, and the failure may
 /// be for an expectation against a property derived from the value at the root
-/// of the subject. For example, in `checkThat([]).length.equals(1)` the
+/// of the subject. For example, in `check([]).length.equals(1)` the
 /// specific value that gets rejected is `0` from the length of the list, and
 /// the subject that sees the rejection is nested with the label "has length".
-class FailureDetail {
+final class FailureDetail {
   /// A description of all the conditions the subject was expected to satisfy.
   ///
   /// Each subject has a label. At the root the label is typically "a <Type>"
@@ -662,7 +967,7 @@
 }
 
 /// A description of a value that failed an expectation.
-class Rejection {
+final class Rejection {
   /// A description of the actual value as it relates to the expectation.
   ///
   /// This may use [literal] to show a String representation of the value, or it
@@ -702,89 +1007,3 @@
 
   Rejection({this.actual = const [], this.which});
 }
-
-class ConditionSubject<T> implements Subject<T>, Condition<T> {
-  ConditionSubject._();
-
-  @override
-  void apply(Subject<T> subject) {
-    _context.apply(subject);
-  }
-
-  @override
-  Future<void> applyAsync(Subject<T> subject) async {
-    await _context.applyAsync(subject);
-  }
-
-  @override
-  final _ReplayContext<T> _context = _ReplayContext();
-
-  @override
-  String toString() {
-    return ['A value that:', ...describe(_context)].join('\n');
-  }
-}
-
-class _ReplayContext<T> implements Context<T>, Condition<T> {
-  final _interactions = <FutureOr<void> Function(Context<T>)>[];
-
-  @override
-  void apply(Subject<T> subject) {
-    for (var interaction in _interactions) {
-      interaction(subject.context);
-    }
-  }
-
-  @override
-  Future<void> applyAsync(Subject<T> subject) async {
-    for (var interaction in _interactions) {
-      await interaction(subject.context);
-    }
-  }
-
-  @override
-  void expect(
-      Iterable<String> Function() clause, Rejection? Function(T) predicate) {
-    _interactions.add((c) {
-      c.expect(clause, predicate);
-    });
-  }
-
-  @override
-  Future<void> expectAsync<R>(Iterable<String> Function() clause,
-      FutureOr<Rejection?> Function(T) predicate) async {
-    _interactions.add((c) async {
-      await c.expectAsync(clause, predicate);
-    });
-  }
-
-  @override
-  void expectUnawaited(Iterable<String> Function() clause,
-      void Function(T, void Function(Rejection)) predicate) {
-    _interactions.add((c) {
-      c.expectUnawaited(clause, predicate);
-    });
-  }
-
-  @override
-  Subject<R> nest<R>(String label, Extracted<R> Function(T p1) extract,
-      {bool atSameLevel = false}) {
-    final nestedContext = _ReplayContext<R>();
-    _interactions.add((c) {
-      var result = c.nest(label, extract, atSameLevel: atSameLevel);
-      nestedContext.apply(result);
-    });
-    return Subject._(nestedContext);
-  }
-
-  @override
-  Future<Subject<R>> nestAsync<R>(
-      String label, FutureOr<Extracted<R>> Function(T) extract) async {
-    final nestedContext = _ReplayContext<R>();
-    _interactions.add((c) async {
-      var result = await c.nestAsync(label, extract);
-      await nestedContext.applyAsync(result);
-    });
-    return Subject._(nestedContext);
-  }
-}
diff --git a/pkgs/checks/lib/src/collection_equality.dart b/pkgs/checks/lib/src/collection_equality.dart
index bd11947..aa11bcf 100644
--- a/pkgs/checks/lib/src/collection_equality.dart
+++ b/pkgs/checks/lib/src/collection_equality.dart
@@ -10,12 +10,22 @@
 /// are unequal to the elements of [expected].
 ///
 /// {@template deep_collection_equals}
-/// Elements, keys, or values, which are a collections are deeply compared for
-/// equality, and do not use the native identity based equality or custom
-/// equality operator overrides.
-/// Elements, keys, or values, which are a [Condition] instances are checked
-/// against actual values.
-/// All other value or key types use `operator ==`.
+/// Elements, keys, or values within [expected] which are a collections are
+/// deeply compared for equality with a collection in the same position within
+/// [actual]. Elements which are collection types are note compared with the
+/// native identity based equality or custom equality operator overrides.
+///
+/// Elements, keys, or values within [expected] which are `Condition` callbacks
+/// are run against the value in the same position within [actual].
+/// Condition callbacks must take a `Subject<Object?>` or `Subject<dynamic>` and
+/// may not use a more specific generic.
+/// Use `(Subject<Object?> s) => s.isA<Type>()` to check expectations for
+/// specific element types.
+/// Note also that the argument type `Subject<Object?>` cannot be inferred and
+/// must be explicit in the function definition.
+///
+/// Elements, keys, or values within [expected] which are any other type are
+/// compared using `operator ==` equality.
 ///
 /// Comparing sets or maps will have a runtime which is polynomial on the the
 /// size of those collections. Does not use [Set.contains] or [Map.containsKey],
@@ -250,7 +260,7 @@
   final indexedExpected = expected.toList();
   final indexedActual = actual.toList();
   final adjacency = <List<int>>[];
-  for (int i = 0; i < indexedExpected.length; i++) {
+  for (var i = 0; i < indexedExpected.length; i++) {
     final expectedElement = indexedExpected[i];
     final pairs = [
       for (var j = 0; j < indexedActual.length; j++)
@@ -303,7 +313,7 @@
 
   bool bfs() {
     final queue = Queue<int>();
-    for (int leftIndex = 0; leftIndex < leftLength; leftIndex++) {
+    for (var leftIndex = 0; leftIndex < leftLength; leftIndex++) {
       if (leftPairs[leftIndex] == rightLength) {
         distances[leftIndex] = 0;
         queue.add(leftIndex);
@@ -342,7 +352,7 @@
   }
 
   while (bfs()) {
-    for (int leftIndex = 0; leftIndex < leftLength; leftIndex++) {
+    for (var leftIndex = 0; leftIndex < leftLength; leftIndex++) {
       if (leftPairs[leftIndex] == rightLength) {
         dfs(leftIndex);
       }
diff --git a/pkgs/checks/lib/src/describe.dart b/pkgs/checks/lib/src/describe.dart
index 7493c12..c0c3560 100644
--- a/pkgs/checks/lib/src/describe.dart
+++ b/pkgs/checks/lib/src/describe.dart
@@ -4,6 +4,8 @@
 
 import 'dart:convert';
 
+import 'checks.dart' show Condition, describe;
+
 /// Returns a pretty-printed representation of [object].
 ///
 /// When possible, lines will be kept under [_maxLineLength]. This isn't
@@ -59,6 +61,9 @@
         .map((line) => line.replaceAll("'", r"\'"))
         .toList();
     return prefixFirst("'", postfixLast("'", escaped));
+  } else if (object is Condition) {
+    final value = ['A value that:', ...describe(object)];
+    return isTopLevel ? prefixFirst('<', postfixLast('>', value)) : value;
   } else {
     final value = const LineSplitter().convert(object.toString());
     return isTopLevel ? prefixFirst('<', postfixLast('>', value)) : value;
diff --git a/pkgs/checks/lib/src/extensions/async.dart b/pkgs/checks/lib/src/extensions/async.dart
index ff54f4e..8f2f073 100644
--- a/pkgs/checks/lib/src/extensions/async.dart
+++ b/pkgs/checks/lib/src/extensions/async.dart
@@ -11,23 +11,26 @@
 extension FutureChecks<T> on Subject<Future<T>> {
   /// Expects that the `Future` completes to a value without throwing.
   ///
-  /// Returns a future that completes to a [Subject] on the result once the
-  /// future completes.
-  ///
   /// Fails if the future completes as an error.
-  Future<Subject<T>> completes() =>
-      context.nestAsync<T>('completes to a value', (actual) async {
-        try {
-          return Extracted.value(await actual);
-        } catch (e, st) {
-          return Extracted.rejection(actual: [
-            'a future that completes as an error'
-          ], which: [
-            ...prefixFirst('threw ', postfixLast(' at:', literal(e))),
-            ...(const LineSplitter()).convert(st.toString())
-          ]);
-        }
-      });
+  ///
+  /// Pass [completionCondition] to check expectations on the completion result.
+  ///
+  /// The returned future will complete when the subject future has completed,
+  /// and [completionCondition] has optionally been checked.
+  Future<void> completes([AsyncCondition<T>? completionCondition]) async {
+    await context.nestAsync<T>(() => ['completes to a value'], (actual) async {
+      try {
+        return Extracted.value(await actual);
+      } catch (e, st) {
+        return Extracted.rejection(actual: [
+          'a future that completes as an error'
+        ], which: [
+          ...prefixFirst('threw ', postfixLast(' at:', literal(e))),
+          ...const LineSplitter().convert(st.toString())
+        ]);
+      }
+    }, completionCondition);
+  }
 
   /// Expects that the `Future` never completes as a value or an error.
   ///
@@ -48,7 +51,7 @@
           'a future that completed as an error:'
         ], which: [
           ...prefixFirst('threw ', literal(e)),
-          ...(const LineSplitter()).convert(st.toString())
+          ...const LineSplitter().convert(st.toString())
         ]));
       }));
     });
@@ -56,28 +59,34 @@
 
   /// Expects that the `Future` completes as an error.
   ///
-  /// Returns a future that completes to a [Subject] on the error once the
-  /// future completes as an error.
-  ///
   /// Fails if the future completes to a value.
-  Future<Subject<E>> throws<E extends Object>() => context.nestAsync<E>(
-          'completes to an error${E == Object ? '' : ' of type $E'}',
-          (actual) async {
-        try {
-          return Extracted.rejection(
-              actual: prefixFirst('completed to ', literal(await actual)),
-              which: ['did not throw']);
-        } on E catch (e) {
-          return Extracted.value(e);
-        } catch (e, st) {
-          return Extracted.rejection(
-              actual: prefixFirst('completed to error ', literal(e)),
-              which: [
-                'threw an exception that is not a $E at:',
-                ...(const LineSplitter()).convert(st.toString())
-              ]);
-        }
-      });
+  ///
+  /// Pass [errorCondition] to check expectations on the error thrown by the
+  /// future.
+  ///
+  /// The returned future will complete when the subject future has completed,
+  /// and [errorCondition] has optionally been checked.
+  Future<void> throws<E extends Object>(
+      [AsyncCondition<E>? errorCondition]) async {
+    await context.nestAsync<E>(
+        () => ['completes to an error${E == Object ? '' : ' of type $E'}'],
+        (actual) async {
+      try {
+        return Extracted.rejection(
+            actual: prefixFirst('completed to ', literal(await actual)),
+            which: ['did not throw']);
+      } on E catch (e) {
+        return Extracted.value(e);
+      } catch (e, st) {
+        return Extracted.rejection(
+            actual: prefixFirst('completed to error ', literal(e)),
+            which: [
+              'threw an exception that is not a $E at:',
+              ...const LineSplitter().convert(st.toString())
+            ]);
+      }
+    }, errorCondition);
+  }
 }
 
 /// Expectations on a [StreamQueue].
@@ -104,67 +113,82 @@
 
   /// Expect that the `Stream` emits a value without first emitting an error.
   ///
-  /// Returns a `Future` that completes to a [Subject] on the next event emitted
-  /// by the stream.
-  ///
   /// Fails if the stream emits an error instead of a value, or closes without
   /// emitting a value.
-  Future<Subject<T>> emits() =>
-      context.nestAsync<T>('emits a value', (actual) async {
-        if (!await actual.hasNext) {
-          return Extracted.rejection(
-              actual: ['a stream'],
-              which: ['closed without emitting enough values']);
-        }
-        try {
-          await actual.peek;
-          return Extracted.value(await actual.next);
-        } catch (e, st) {
-          return Extracted.rejection(
-              actual: prefixFirst('a stream with error ', literal(e)),
-              which: [
-                'emitted an error instead of a value at:',
-                ...(const LineSplitter()).convert(st.toString())
-              ]);
-        }
-      });
+  ///
+  /// If an error is emitted the queue will be left in its original state, the
+  /// error will not be consumed.
+  /// If an event is emitted, it will be consumed from the queue.
+  ///
+  /// Pass [emittedCondition] to check expectations on the value emitted by the
+  /// stream.
+  ///
+  /// The returned future will complete when the stream has emitted, errored, or
+  /// ended, and the [emittedCondition] has optionally been checked.
+  Future<void> emits([AsyncCondition<T>? emittedCondition]) async {
+    await context.nestAsync<T>(() => ['emits a value'], (actual) async {
+      if (!await actual.hasNext) {
+        return Extracted.rejection(
+            actual: ['a stream'],
+            which: ['closed without emitting enough values']);
+      }
+      try {
+        await actual.peek;
+        return Extracted.value(await actual.next);
+      } catch (e, st) {
+        return Extracted.rejection(
+            actual: prefixFirst('a stream with error ', literal(e)),
+            which: [
+              'emitted an error instead of a value at:',
+              ...const LineSplitter().convert(st.toString())
+            ]);
+      }
+    }, emittedCondition);
+  }
 
   /// Expects that the stream emits an error of type [E].
   ///
-  /// Returns a [Subject] on the error's value.
-  ///
   /// Fails if the stream emits any value.
   /// Fails if the stream emits an error with an incorrect type.
   /// Fails if the stream closes without emitting an error.
   ///
-  /// If this expectation fails, the source queue will be left in it's original
-  /// state.
-  /// If this expectation succeeds, consumes the error event.
-  Future<Subject<E>> emitsError<E extends Object>() =>
-      context.nestAsync('emits an error${E == Object ? '' : ' of type $E'}',
-          (actual) async {
-        if (!await actual.hasNext) {
-          return Extracted.rejection(
-              actual: ['a stream'],
-              which: ['closed without emitting an expected error']);
-        }
-        try {
-          final value = await actual.peek;
-          return Extracted.rejection(
-              actual: prefixFirst('a stream emitting value ', literal(value)),
-              which: ['closed without emitting an error']);
-        } on E catch (e) {
-          await actual.next.then<void>((_) {}, onError: (_) {});
-          return Extracted.value(e);
-        } catch (e, st) {
-          return Extracted.rejection(
-              actual: prefixFirst('a stream with error ', literal(e)),
-              which: [
-                'emitted an error which is not $E at:',
-                ...(const LineSplitter()).convert(st.toString())
-              ]);
-        }
-      });
+  /// If an event is emitted the queue will be left in its original state, the
+  /// event will not be consumed.
+  /// If an error is emitted, it will be consumed from the queue.
+  ///
+  /// Pass [errorCondition] to check expectations on the error emitted by the
+  /// stream.
+  ///
+  /// The returned future will complete when the stream has emitted, errored, or
+  /// ended, and the [errorCondition] has optionally been checked.
+  Future<void> emitsError<E extends Object>(
+      [AsyncCondition<E>? errorCondition]) async {
+    await context.nestAsync<E>(
+        () => ['emits an error${E == Object ? '' : ' of type $E'}'],
+        (actual) async {
+      if (!await actual.hasNext) {
+        return Extracted.rejection(
+            actual: ['a stream'],
+            which: ['closed without emitting an expected error']);
+      }
+      try {
+        final value = await actual.peek;
+        return Extracted.rejection(
+            actual: prefixFirst('a stream emitting value ', literal(value)),
+            which: ['closed without emitting an error']);
+      } on E catch (e) {
+        await actual.next.then<void>((_) {}, onError: (_) {});
+        return Extracted.value(e);
+      } catch (e, st) {
+        return Extracted.rejection(
+            actual: prefixFirst('a stream with error ', literal(e)),
+            which: [
+              'emitted an error which is not $E at:',
+              ...const LineSplitter().convert(st.toString())
+            ]);
+      }
+    }, errorCondition);
+  }
 
   /// Expects that the `Stream` emits any number of events before emitting an
   /// event that satisfies [condition].
@@ -179,7 +203,7 @@
   /// state.
   /// If this expectation succeeds, consumes the matching event and all prior
   /// events.
-  Future<void> emitsThrough(Condition<T> condition) async {
+  Future<void> emitsThrough(AsyncCondition<T> condition) async {
     await _expectAsync(
         () => [
               'emits any values then emits a value that:',
@@ -205,9 +229,9 @@
   /// conditions.
   ///
   /// ```dart
-  /// await checkThat(StreamQueue(someStream)).inOrder([
-  ///   it()..emits().that(equals(0)),
-  ///   it()..emits().that(equals(1)),
+  /// await check(someStream).withQueue.inOrder([
+  ///   (s) => s.emits(equals(0)),
+  ///   (s) => s.emits(equals(1)),
   //  ]);
   /// ```
   ///
@@ -215,7 +239,8 @@
   /// state.
   /// If this expectation succeeds, consumes as many events from the source
   /// stream as are consumed by all the conditions.
-  Future<void> inOrder(Iterable<Condition<StreamQueue<T>>> conditions) async {
+  Future<void> inOrder(
+      Iterable<AsyncCondition<StreamQueue<T>>> conditions) async {
     conditions = conditions.toList();
     final descriptions = <String>[];
     await _expectAsync(
@@ -260,7 +285,8 @@
   /// If this expectation succeeds, consumes the same events from the source
   /// queue as the satisfied condition. If multiple conditions are satisfied,
   /// chooses the condition which consumed the most events.
-  Future<void> anyOf(Iterable<Condition<StreamQueue<T>>> conditions) async {
+  Future<void> anyOf(
+      Iterable<AsyncCondition<StreamQueue<T>>> conditions) async {
     conditions = conditions.toList();
     if (conditions.isEmpty) {
       throw ArgumentError('conditions may not be empty');
@@ -341,7 +367,7 @@
   /// state.
   /// If this expectation succeeds, consumes all the events that did not satisfy
   /// [condition] until the end of the stream.
-  Future<void> neverEmits(Condition<T> condition) async {
+  Future<void> neverEmits(AsyncCondition<T> condition) async {
     await _expectAsync(
         () => ['never emits a value that:', ...describe(condition)],
         (actual) async {
@@ -367,7 +393,7 @@
   ///
   /// If a non-matching event is emitted, no events are consumed.
   /// If a matching event is emitted, that event is consumed.
-  Future<void> mayEmit(Condition<T> condition) async {
+  Future<void> mayEmit(AsyncCondition<T> condition) async {
     await context
         .expectAsync(() => ['may emit a value that:', ...describe(condition)],
             (actual) async {
@@ -392,7 +418,7 @@
   /// - A non-matching event is emitted.
   /// - An error is emitted.
   /// - The stream closes.
-  Future<void> mayEmitMultiple(Condition<T> condition) async {
+  Future<void> mayEmitMultiple(AsyncCondition<T> condition) async {
     await context
         .expectAsync(() => ['may emit a value that:', ...describe(condition)],
             (actual) async {
@@ -429,32 +455,14 @@
           'a stream'
         ], which: [
           ...prefixFirst('emitted an unexpected error: ', literal(e)),
-          ...(const LineSplitter()).convert(st.toString())
+          ...const LineSplitter().convert(st.toString())
         ]);
       }
     });
   }
 }
 
-extension ChainAsync<T> on Future<Subject<T>> {
-  /// Checks the expectations in [condition] against the result of this
-  /// `Future`.
-  ///
-  /// Extensions written on [Subject] cannot be invoked on a `Future<Subject>`.
-  /// This method allows adding expectations for the value without awaiting an
-  /// expression that would need parenthesis.
-  ///
-  /// ```dart
-  /// await checkThat(someFuture).completes().which(equals('expected'));
-  /// // or, with the intermediate `await`:
-  /// (await checkThat(someFuture).completes()).equals('expected');
-  /// ```
-  Future<void> which(Condition<T> condition) async {
-    await condition.applyAsync(await this);
-  }
-}
-
-extension StreamQueueWrap<T> on Subject<Stream<T>> {
+extension WithQueueExtension<T> on Subject<Stream<T>> {
   /// Wrap the stream in a [StreamQueue] to allow using checks from
   /// [StreamChecks].
   ///
@@ -462,6 +470,6 @@
   /// so that they can support conditional expectations and check multiple
   /// possibilities from the same point in the stream.
   Subject<StreamQueue<T>> get withQueue =>
-      context.nest('', (actual) => Extracted.value(StreamQueue(actual)),
+      context.nest(() => [], (actual) => Extracted.value(StreamQueue(actual)),
           atSameLevel: true);
 }
diff --git a/pkgs/checks/lib/src/extensions/core.dart b/pkgs/checks/lib/src/extensions/core.dart
index 1fc34be..da1eac1 100644
--- a/pkgs/checks/lib/src/extensions/core.dart
+++ b/pkgs/checks/lib/src/extensions/core.dart
@@ -2,21 +2,26 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:checks/checks.dart';
+import 'dart:convert';
+
 import 'package:checks/context.dart';
+import 'package:meta/meta.dart' as meta;
 
 extension CoreChecks<T> on Subject<T> {
   /// Extracts a property of the value for further expectations.
   ///
   /// Sets up a clause that the value "has [name] that:" followed by any
   /// expectations applied to the returned [Subject].
+  @meta.useResult
   Subject<R> has<R>(R Function(T) extract, String name) {
-    return context.nest('has $name', (T value) {
+    return context.nest(() => ['has $name'], (value) {
       try {
         return Extracted.value(extract(value));
-      } catch (_) {
-        return Extracted.rejection(
-            which: ['threw while trying to read property']);
+      } catch (e, st) {
+        return Extracted.rejection(which: [
+          ...prefixFirst('threw while trying to read $name: ', literal(e)),
+          ...const LineSplitter().convert(st.toString())
+        ]);
       }
     });
   }
@@ -28,13 +33,13 @@
   /// in a way that would conflict.
   ///
   /// ```
-  /// checkThat(something)
+  /// check(something)
   ///   ..has((s) => s.foo, 'foo').equals(expectedFoo)
-  ///   ..has((s) => s.bar, 'bar').which(it()
+  ///   ..has((s) => s.bar, 'bar').which((b) => b
   ///     ..isLessThan(10)
   ///     ..isGreaterThan(0));
   /// ```
-  void which(Condition<T> condition) => condition.apply(this);
+  void which(Condition<T> condition) => condition(this);
 
   /// Check that the expectations invoked in [condition] are not satisfied by
   /// this value.
@@ -71,7 +76,7 @@
   ///
   /// If the value is a [T], returns a [Subject] for further expectations.
   Subject<R> isA<R>() {
-    return context.nest<R>('is a $R', (actual) {
+    return context.nest<R>(() => ['is a $R'], (actual) {
       if (actual is! R) {
         return Extracted.rejection(which: ['Is a ${actual.runtimeType}']);
       }
@@ -100,11 +105,15 @@
 /// Returns a [Condition] checking that the actual value is equal to [expected]
 /// by operator `==`.
 ///
-/// This is a shortcut for `it<T>()..equals(expected)`.
-Condition<T> equals<T>(T expected) => T == String
-    // String specializes `equals` with a better failure
-    ? ((it<String>()..equals(expected as String)) as Condition<T>)
-    : (it<T>()..equals(expected));
+/// This is a shortcut for `(Subject<T> it) => it..equals(expected)`.
+Condition<T> equals<T>(T expected) => (Subject<T> subject) {
+      if (subject is Subject<String> && expected is String) {
+        // String specializes `equals` with a better failure
+        (subject as Subject<String>).equals(expected);
+      } else {
+        subject.equals(expected);
+      }
+    };
 
 extension BoolChecks on Subject<bool> {
   void isTrue() {
@@ -126,9 +135,9 @@
   }
 }
 
-extension NullabilityChecks<T> on Subject<T?> {
+extension NullableChecks<T> on Subject<T?> {
   Subject<T> isNotNull() {
-    return context.nest<T>('is not null', (actual) {
+    return context.nest<T>(() => ['is not null'], (actual) {
       if (actual == null) return Extracted.rejection();
       return Extracted.value(actual);
     }, atSameLevel: true);
@@ -141,3 +150,47 @@
     });
   }
 }
+
+extension ComparableChecks<T> on Subject<Comparable<T>> {
+  /// Expects that this value is greater than [other].
+  void isGreaterThan(T other) {
+    context.expect(() => prefixFirst('is greater than ', literal(other)),
+        (actual) {
+      if (actual.compareTo(other) > 0) return null;
+      return Rejection(
+          which: prefixFirst('is not greater than ', literal(other)));
+    });
+  }
+
+  /// Expects that this value is greater than or equal to [other].
+  void isGreaterOrEqual(T other) {
+    context.expect(
+        () => prefixFirst('is greater than or equal to ', literal(other)),
+        (actual) {
+      if (actual.compareTo(other) >= 0) return null;
+      return Rejection(
+          which:
+              prefixFirst('is not greater than or equal to ', literal(other)));
+    });
+  }
+
+  /// Expects that this value is less than [other].
+  void isLessThan(T other) {
+    context.expect(() => prefixFirst('is less than ', literal(other)),
+        (actual) {
+      if (actual.compareTo(other) < 0) return null;
+      return Rejection(which: prefixFirst('is not less than ', literal(other)));
+    });
+  }
+
+  /// Expects that this value is less than or equal to [other].
+  void isLessOrEqual(T other) {
+    context
+        .expect(() => prefixFirst('is less than or equal to ', literal(other)),
+            (actual) {
+      if (actual.compareTo(other) <= 0) return null;
+      return Rejection(
+          which: prefixFirst('is not less than or equal to ', literal(other)));
+    });
+  }
+}
diff --git a/pkgs/checks/lib/src/extensions/function.dart b/pkgs/checks/lib/src/extensions/function.dart
index 7e20aca..5246cba 100644
--- a/pkgs/checks/lib/src/extensions/function.dart
+++ b/pkgs/checks/lib/src/extensions/function.dart
@@ -4,7 +4,7 @@
 
 import 'package:checks/context.dart';
 
-extension ThrowsCheck<T> on Subject<T Function()> {
+extension FunctionChecks<T> on Subject<T Function()> {
   /// Expects that a function throws synchronously when it is called.
   ///
   /// If the function synchronously throws a value of type [E], return a
@@ -17,7 +17,7 @@
   /// fail. Instead invoke the function and check the expectation on the
   /// returned [Future].
   Subject<E> throws<E>() {
-    return context.nest<E>('throws an error of type $E', (actual) {
+    return context.nest<E>(() => ['throws an error of type $E'], (actual) {
       try {
         final result = actual();
         return Extracted.rejection(
@@ -40,7 +40,7 @@
   ///
   /// If the function throws synchronously, this expectation will fail.
   Subject<T> returnsNormally() {
-    return context.nest<T>('returns a value', (actual) {
+    return context.nest<T>(() => ['returns a value'], (actual) {
       try {
         return Extracted.value(actual());
       } catch (e, st) {
diff --git a/pkgs/checks/lib/src/extensions/iterable.dart b/pkgs/checks/lib/src/extensions/iterable.dart
index 9cf67ba..d53ea54 100644
--- a/pkgs/checks/lib/src/extensions/iterable.dart
+++ b/pkgs/checks/lib/src/extensions/iterable.dart
@@ -9,9 +9,38 @@
 
 extension IterableChecks<T> on Subject<Iterable<T>> {
   Subject<int> get length => has((l) => l.length, 'length');
-  Subject<T> get first => has((l) => l.first, 'first element');
-  Subject<T> get last => has((l) => l.last, 'last element');
-  Subject<T> get single => has((l) => l.single, 'single element');
+
+  Subject<T> get first => context.nest(() => ['has first element'], (actual) {
+        final iterator = actual.iterator;
+        if (!iterator.moveNext()) {
+          return Extracted.rejection(which: ['has no elements']);
+        }
+        return Extracted.value(iterator.current);
+      });
+
+  Subject<T> get last => context.nest(() => ['has last element'], (actual) {
+        final iterator = actual.iterator;
+        if (!iterator.moveNext()) {
+          return Extracted.rejection(which: ['has no elements']);
+        }
+        var current = iterator.current;
+        while (iterator.moveNext()) {
+          current = iterator.current;
+        }
+        return Extracted.value(current);
+      });
+
+  Subject<T> get single => context.nest(() => ['has single element'], (actual) {
+        final iterator = actual.iterator;
+        if (!iterator.moveNext()) {
+          return Extracted.rejection(which: ['has no elements']);
+        }
+        final value = iterator.current;
+        if (iterator.moveNext()) {
+          return Extracted.rejection(which: ['has more than one element']);
+        }
+        return Extracted.value(value);
+      });
 
   void isEmpty() {
     context.expect(() => const ['is empty'], (actual) {
@@ -23,7 +52,7 @@
   void isNotEmpty() {
     context.expect(() => const ['is not empty'], (actual) {
       if (actual.isNotEmpty) return null;
-      return Rejection(which: ['is not empty']);
+      return Rejection(which: ['is empty']);
     });
   }
 
@@ -47,18 +76,18 @@
   /// For example, the following will succeed:
   ///
   /// ```dart
-  /// checkThat([1, 0, 2, 0, 3]).containsInOrder([1, 2, 3]);
+  /// check([1, 0, 2, 0, 3]).containsInOrder([1, 2, 3]);
   /// ```
   ///
   /// Values in [elements] may be a `T`, a `Condition<T>`, or a
-  /// `Condition<dynamic>`. If an expectation is a [Condition] it will be
+  /// `Condition<Object?>`. If an expectation is a condition callback it will be
   /// checked against the actual values, and any other expectations, including
-  /// those that are not a `T` or a `Condition`, will be compared with the
-  /// equality operator.
+  /// those that are not a `T` or a condition callback, will be compared with
+  /// the equality operator.
   ///
   /// ```dart
-  /// checkThat([1, 0, 2, 0, 3])
-  ///   .containsInOrder([1, it<int>()..isGreaterThan(1), 3]);
+  /// check([1, 0, 2, 0, 3])
+  ///   .containsInOrder([1, (Subject<int> v) => v.isGreaterThan(1), 3]);
   /// ```
   void containsInOrder(Iterable<Object?> elements) {
     context.expect(() => prefixFirst('contains, in order: ', literal(elements)),
diff --git a/pkgs/checks/lib/src/extensions/map.dart b/pkgs/checks/lib/src/extensions/map.dart
index b836f1e..4984b5f 100644
--- a/pkgs/checks/lib/src/extensions/map.dart
+++ b/pkgs/checks/lib/src/extensions/map.dart
@@ -14,11 +14,11 @@
   Subject<Iterable<V>> get values => has((m) => m.values, 'values');
   Subject<int> get length => has((m) => m.length, 'length');
   Subject<V> operator [](K key) {
-    final keyString = literal(key).join(r'\n');
-    return context.nest('contains a value for $keyString', (actual) {
+    return context.nest(
+        () => prefixFirst('contains a value for ', literal(key)), (actual) {
       if (!actual.containsKey(key)) {
         return Extracted.rejection(
-            which: ['does not contain the key $keyString']);
+            which: prefixFirst('does not contain the key ', literal(key)));
       }
       return Extracted.value(actual[key] as V);
     });
@@ -40,10 +40,10 @@
 
   /// Expects that the map contains [key] according to [Map.containsKey].
   void containsKey(K key) {
-    final keyString = literal(key).join(r'\n');
-    context.expect(() => ['contains key $keyString'], (actual) {
+    context.expect(() => prefixFirst('contains key ', literal(key)), (actual) {
       if (actual.containsKey(key)) return null;
-      return Rejection(which: ['does not contain key $keyString']);
+      return Rejection(
+          which: prefixFirst('does not contain key ', literal(key)));
     });
   }
 
@@ -68,10 +68,11 @@
 
   /// Expects that the map contains [value] according to [Map.containsValue].
   void containsValue(V value) {
-    final valueString = literal(value).join(r'\n');
-    context.expect(() => ['contains value $valueString'], (actual) {
+    context.expect(() => prefixFirst('contains value ', literal(value)),
+        (actual) {
       if (actual.containsValue(value)) return null;
-      return Rejection(which: ['does not contain value $valueString']);
+      return Rejection(
+          which: prefixFirst('does not contain value ', literal(value)));
     });
   }
 
diff --git a/pkgs/checks/lib/src/extensions/math.dart b/pkgs/checks/lib/src/extensions/math.dart
index b087aef..c201b7a 100644
--- a/pkgs/checks/lib/src/extensions/math.dart
+++ b/pkgs/checks/lib/src/extensions/math.dart
@@ -5,38 +5,6 @@
 import 'package:checks/context.dart';
 
 extension NumChecks on Subject<num> {
-  /// Expects that this number is greater than [other].
-  void isGreaterThan(num other) {
-    context.expect(() => ['is greater than <$other>'], (actual) {
-      if (actual > other) return null;
-      return Rejection(which: ['is not greater than <$other>']);
-    });
-  }
-
-  /// Expects that this number is greater than or equal to [other].
-  void isGreaterOrEqual(num other) {
-    context.expect(() => ['is greater than or equal to <$other>'], (actual) {
-      if (actual >= other) return null;
-      return Rejection(which: ['is not greater than or equal to <$other>']);
-    });
-  }
-
-  /// Expects that this number is less than [other].
-  void isLessThan(num other) {
-    context.expect(() => ['is less than <$other>'], (actual) {
-      if (actual < other) return null;
-      return Rejection(which: ['is not less than <$other>']);
-    });
-  }
-
-  /// Expects that this number is less than or equal to [other].
-  void isLessOrEqual(num other) {
-    context.expect(() => ['is less than or equal to <$other>'], (actual) {
-      if (actual <= other) return null;
-      return Rejection(which: ['is not less than or equal to <$other>']);
-    });
-  }
-
   /// Expects that [num.isNaN] is true.
   void isNaN() {
     context.expect(() => ['is not a number (NaN)'], (actual) {
diff --git a/pkgs/checks/lib/src/extensions/string.dart b/pkgs/checks/lib/src/extensions/string.dart
index 9c790cd..1a00ef8 100644
--- a/pkgs/checks/lib/src/extensions/string.dart
+++ b/pkgs/checks/lib/src/extensions/string.dart
@@ -59,10 +59,18 @@
     );
   }
 
-  /// Expects that the string matches the regular expression [expected].
-  void matches(RegExp expected) {
+  /// Expects that the string matches the pattern [expected].
+  ///
+  /// Fails if [expected] returns an empty result from calling `allMatches` with
+  /// the value.
+  ///
+  /// ```
+  /// check(actual).matchesPattern('abc');
+  /// check(actual).matchesPattern(RegExp(r'\d'));
+  /// ```
+  void matchesPattern(Pattern expected) {
     context.expect(() => prefixFirst('matches ', literal(expected)), (actual) {
-      if (expected.hasMatch(actual)) return null;
+      if (expected.allMatches(actual).isNotEmpty) return null;
       return Rejection(
           which: prefixFirst('does not match ', literal(expected)));
     });
@@ -73,7 +81,7 @@
   ///
   /// For example, the following will succeed:
   ///
-  ///     checkThat('abcdefg').containsInOrder(['a','e']);
+  ///     check('abcdefg').containsInOrder(['a','e']);
   void containsInOrder(Iterable<String> expected) {
     context.expect(() => prefixFirst('contains, in order: ', literal(expected)),
         (actual) {
@@ -118,12 +126,12 @@
   ///
   /// For example the following will succeed:
   ///
-  ///     checkThat(' hello   world ').equalsIgnoringWhitespace('hello world');
+  ///     check(' hello   world ').equalsIgnoringWhitespace('hello world');
   ///
   /// While the following will fail:
   ///
-  ///     checkThat('helloworld').equalsIgnoringWhitespace('hello world');
-  ///     checkThat('he llo world').equalsIgnoringWhitespace('hello world');
+  ///     check('helloworld').equalsIgnoringWhitespace('hello world');
+  ///     check('he llo world').equalsIgnoringWhitespace('hello world');
   void equalsIgnoringWhitespace(String expected) {
     context.expect(
         () => prefixFirst('equals ignoring whitespace ', literal(expected)),
diff --git a/pkgs/checks/pubspec.yaml b/pkgs/checks/pubspec.yaml
index 7702773..10e3728 100644
--- a/pkgs/checks/pubspec.yaml
+++ b/pkgs/checks/pubspec.yaml
@@ -1,18 +1,18 @@
 name: checks
-version: 0.1.1-dev
+version: 0.3.0-wip
 description: >-
   A framework for checking values against expectations and building custom
   expectations.
 repository: https://github.com/dart-lang/test/tree/master/pkgs/checks
 
 environment:
-  sdk: ">=2.18.0 <3.0.0"
+  sdk: ^3.0.0
 
 dependencies:
   async: ^2.8.0
   meta: ^1.9.0
-  test_api: ^0.4.0
+  test_api: ">=0.5.0 <0.7.0"
 
 dev_dependencies:
+  dart_flutter_team_lints: ^1.0.0
   test: ^1.21.3
-  lints: ^2.0.0
diff --git a/pkgs/checks/pubspec_overrides.yaml b/pkgs/checks/pubspec_overrides.yaml
new file mode 100644
index 0000000..7d9aba4
--- /dev/null
+++ b/pkgs/checks/pubspec_overrides.yaml
@@ -0,0 +1,7 @@
+dependency_overrides:
+  test_api:
+    path: ../test_api
+  test_core:
+    path: ../test_core
+  test:
+    path: ../test
diff --git a/pkgs/checks/test/context_test.dart b/pkgs/checks/test/context_test.dart
new file mode 100644
index 0000000..f523115
--- /dev/null
+++ b/pkgs/checks/test/context_test.dart
@@ -0,0 +1,172 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. 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';
+
+import 'package:async/async.dart' hide Result;
+import 'package:checks/checks.dart';
+import 'package:checks/context.dart';
+import 'package:test/scaffolding.dart';
+import 'package:test_api/hooks.dart';
+import 'package:test_api/hooks_testing.dart';
+
+void main() {
+  group('Context', () {
+    test('expectAsync holds test open', () async {
+      late void Function() callback;
+      final monitor = TestCaseMonitor.start(() {
+        check(null).context.expectAsync(() => [''], (actual) async {
+          final completer = Completer<void>();
+          callback = completer.complete;
+          await completer.future;
+          return null;
+        });
+      });
+      await pumpEventQueue();
+      check(monitor).state.equals(State.running);
+      callback();
+      await monitor.onDone;
+      check(monitor).didPass();
+    });
+
+    test('expectAsync does not hold test open past exception', () async {
+      late void Function() callback;
+      final monitor = TestCaseMonitor.start(() {
+        check(null).context.expectAsync(() => [''], (actual) async {
+          final completer = Completer<void>();
+          callback = completer.complete;
+          await completer.future;
+          throw 'oh no!';
+        });
+      });
+      await pumpEventQueue();
+      check(monitor).state.equals(State.running);
+      callback();
+      await monitor.onDone;
+      check(monitor)
+        ..state.equals(State.failed)
+        ..errors.single.has((e) => e.error, 'error').equals('oh no!');
+    });
+
+    test('nestAsync holds test open', () async {
+      late void Function() callback;
+      final monitor = TestCaseMonitor.start(() {
+        check(null).context.nestAsync(() => [''], (actual) async {
+          final completer = Completer<void>();
+          callback = completer.complete;
+          await completer.future;
+          return Extracted.value(null);
+        }, null);
+      });
+      await pumpEventQueue();
+      check(monitor).state.equals(State.running);
+      callback();
+      await monitor.onDone;
+      check(monitor).didPass();
+    });
+
+    test('nestAsync holds test open past async condition', () async {
+      late void Function() callback;
+      final monitor = TestCaseMonitor.start(() {
+        check(null).context.nestAsync(() => [''], (actual) async {
+          return Extracted.value(null);
+        }, (it) async {
+          final completer = Completer<void>();
+          callback = completer.complete;
+          await completer.future;
+        });
+      });
+      await pumpEventQueue();
+      check(monitor).state.equals(State.running);
+      callback();
+      await monitor.onDone;
+      check(monitor).didPass();
+    });
+
+    test('nestAsync does not hold test open past exception', () async {
+      late void Function() callback;
+      final monitor = TestCaseMonitor.start(() {
+        check(null).context.nestAsync(() => [''], (actual) async {
+          final completer = Completer<void>();
+          callback = completer.complete;
+          await completer.future;
+          throw 'oh no!';
+        }, null);
+      });
+      await pumpEventQueue();
+      check(monitor).state.equals(State.running);
+      callback();
+      await monitor.onDone;
+      check(monitor)
+        ..state.equals(State.failed)
+        ..errors.single.has((e) => e.error, 'error').equals('oh no!');
+    });
+
+    test('expectUnawaited can fail the test after it completes', () async {
+      late void Function() callback;
+      final monitor = await TestCaseMonitor.run(() {
+        check(null).context.expectUnawaited(() => [''], (actual, reject) {
+          final completer = Completer<void>()
+            ..future.then((_) {
+              reject(Rejection(which: ['foo']));
+            });
+          callback = completer.complete;
+        });
+      });
+      check(monitor).state.equals(State.passed);
+      callback();
+      await pumpEventQueue();
+      check(monitor)
+        ..state.equals(State.failed)
+        ..errors.unorderedMatches([
+          (it) => it
+              .has((e) => e.error, 'error')
+              .isA<TestFailure>()
+              .has((f) => f.message, 'message')
+              .isNotNull()
+              .endsWith('Which: foo'),
+          (it) => it
+              .has((e) => e.error, 'error')
+              .isA<String>()
+              .startsWith('This test failed after it had already completed.')
+        ]);
+    });
+  });
+
+  group('SkipExtension', () {
+    test('marks the test as skipped', () async {
+      final monitor = await TestCaseMonitor.run(() {
+        check(null).skip('skip').isNotNull();
+      });
+      check(monitor).state.equals(State.skipped);
+    });
+  });
+}
+
+extension _MonitorChecks on Subject<TestCaseMonitor> {
+  Subject<State> get state => has((m) => m.state, 'state');
+  Subject<Iterable<AsyncError>> get errors => has((m) => m.errors, 'errors');
+  Subject<StreamQueue<AsyncError>> get onError =>
+      has((m) => m.onError, 'onError').withQueue;
+
+  /// Expects that the monitored test is completed as success with no errors.
+  ///
+  /// Sets up an unawaited expectation that the test does not emit errors in the
+  /// future in addition to checking there have been no errors yet.
+  void didPass() {
+    errors.isEmpty();
+    state.equals(State.passed);
+    onError.context.expectUnawaited(() => ['emits no further errors'],
+        (actual, reject) async {
+      await for (var error in actual.rest) {
+        reject(Rejection(which: [
+          ...prefixFirst('threw late error', literal(error.error)),
+          ...const LineSplitter().convert(
+              TestHandle.current.formatStackTrace(error.stackTrace).toString())
+        ]));
+      }
+    });
+  }
+}
diff --git a/pkgs/checks/test/describe_test.dart b/pkgs/checks/test/describe_test.dart
index b9b335c..fedd620 100644
--- a/pkgs/checks/test/describe_test.dart
+++ b/pkgs/checks/test/describe_test.dart
@@ -9,13 +9,13 @@
 void main() {
   group('describe', () {
     test('succeeds for empty conditions', () {
-      checkThat(describe(it())).isEmpty();
+      check(describe((_) {})).isEmpty();
     });
     test('includes condition clauses', () {
-      checkThat(describe(equals(1))).deepEquals(['  equals <1>']);
+      check(describe(equals(1))).deepEquals(['  equals <1>']);
     });
     test('includes nested clauses', () {
-      checkThat(describe(it<String>()..length.equals(1))).deepEquals([
+      check(describe<String>((it) => it.length.equals(1))).deepEquals([
         '  has length that:',
         '    equals <1>',
       ]);
diff --git a/pkgs/checks/test/extensions/async_test.dart b/pkgs/checks/test/extensions/async_test.dart
index 280ba54..3484fb2 100644
--- a/pkgs/checks/test/extensions/async_test.dart
+++ b/pkgs/checks/test/extensions/async_test.dart
@@ -16,26 +16,24 @@
   group('FutureChecks', () {
     group('completes', () {
       test('succeeds for a future that completes to a value', () async {
-        await checkThat(_futureSuccess()).completes().which(equals(42));
+        await check(_futureSuccess()).completes(equals(42));
       });
       test('rejects futures which complete as errors', () async {
-        await checkThat(_futureFail()).isRejectedByAsync(
-          it()..completes().which(equals(1)),
+        await check(_futureFail()).isRejectedByAsync(
+          (it) => it.completes(equals(1)),
           actual: ['a future that completes as an error'],
           which: ['threw <UnimplementedError> at:', 'fake trace'],
         );
       });
       test('can be described', () async {
-        await checkThat(it<Future<void>>()..completes())
-            .asyncDescription
-            .which(it()..deepEquals(['  completes to a value']));
-        await checkThat(it<Future<int>>()..completes().which(equals(42)))
-            .asyncDescription
-            .which(it()
-              ..deepEquals([
-                '  completes to a value that:',
-                '    equals <42>',
-              ]));
+        await check((Subject<Future> it) => it.completes())
+            .hasAsyncDescriptionWhich(
+                (it) => it.deepEquals(['  completes to a value']));
+        await check((Subject<Future> it) => it.completes(equals(42)))
+            .hasAsyncDescriptionWhich((it) => it.deepEquals([
+                  '  completes to a value that:',
+                  '    equals <42>',
+                ]));
       });
     });
 
@@ -43,21 +41,20 @@
       test(
           'succeeds for a future that compeletes to an error of the expected type',
           () async {
-        await checkThat(_futureFail())
-            .throws<UnimplementedError>()
-            .which(it()..has((p0) => p0.message, 'message').isNull());
+        await check(_futureFail()).throws<UnimplementedError>(
+            (it) => it.has((p0) => p0.message, 'message').isNull());
       });
       test('fails for futures that complete to a value', () async {
-        await checkThat(_futureSuccess()).isRejectedByAsync(
-          it()..throws(),
+        await check(_futureSuccess()).isRejectedByAsync(
+          (it) => it.throws(),
           actual: ['completed to <42>'],
           which: ['did not throw'],
         );
       });
       test('failes for futures that complete to an error of the wrong type',
           () async {
-        await checkThat(_futureFail()).isRejectedByAsync(
-          it()..throws<StateError>(),
+        await check(_futureFail()).isRejectedByAsync(
+          (it) => it.throws<StateError>(),
           actual: ['completed to error <UnimplementedError>'],
           which: [
             'threw an exception that is not a StateError at:',
@@ -66,31 +63,30 @@
         );
       });
       test('can be described', () async {
-        await checkThat(it<Future<void>>()..throws())
-            .asyncDescription
-            .which(it()..deepEquals(['  completes to an error']));
-        await checkThat(it<Future<void>>()..throws<StateError>())
-            .asyncDescription
-            .which(it()
-              ..deepEquals(['  completes to an error of type StateError']));
+        await check((Subject<Future<void>> it) => it.throws())
+            .hasAsyncDescriptionWhich(
+                (it) => it.deepEquals(['  completes to an error']));
+        await check((Subject<Future<void>> it) => it.throws<StateError>())
+            .hasAsyncDescriptionWhich((it) =>
+                it.deepEquals(['  completes to an error of type StateError']));
       });
     });
 
     group('doesNotComplete', () {
       test('succeeds for a Future that never completes', () async {
-        checkThat(Completer<void>().future).doesNotComplete();
+        check(Completer<void>().future).doesNotComplete();
       });
       test('fails for a Future that completes as a value', () async {
         Object? testFailure;
         runZonedGuarded(() {
           final completer = Completer<String>();
-          checkThat(completer.future).doesNotComplete();
+          check(completer.future).doesNotComplete();
           completer.complete('value');
         }, (e, st) {
           testFailure = e;
         });
         await pumpEventQueue();
-        checkThat(testFailure)
+        check(testFailure)
             .isA<TestFailure>()
             .has((f) => f.message, 'message')
             .isNotNull()
@@ -103,13 +99,13 @@
         Object? testFailure;
         runZonedGuarded(() {
           final completer = Completer<String>();
-          checkThat(completer.future).doesNotComplete();
+          check(completer.future).doesNotComplete();
           completer.completeError('error', StackTrace.fromString('fake trace'));
         }, (e, st) {
           testFailure = e;
         });
         await pumpEventQueue();
-        checkThat(testFailure)
+        check(testFailure)
             .isA<TestFailure>()
             .has((f) => f.message, 'message')
             .isNotNull()
@@ -121,9 +117,9 @@
 fake trace''');
       });
       test('can be described', () async {
-        await checkThat(it<Future<void>>()..doesNotComplete())
-            .asyncDescription
-            .which(it()..deepEquals(['  does not complete']));
+        await check((Subject<Future<void>> it) => it.doesNotComplete())
+            .hasAsyncDescriptionWhich(
+                (it) => it.deepEquals(['  does not complete']));
       });
     });
   });
@@ -131,140 +127,136 @@
   group('StreamChecks', () {
     group('emits', () {
       test('succeeds for a stream that emits a value', () async {
-        await checkThat(_countingStream(5)).emits().which(equals(0));
+        await check(_countingStream(5)).emits(equals(0));
       });
       test('fails for a stream that closes without emitting', () async {
-        await checkThat(_countingStream(0)).isRejectedByAsync(
-          it()..emits(),
+        await check(_countingStream(0)).isRejectedByAsync(
+          (it) => it.emits(),
           actual: ['a stream'],
           which: ['closed without emitting enough values'],
         );
       });
       test('fails for a stream that emits an error', () async {
-        await checkThat(_countingStream(1, errorAt: 0)).isRejectedByAsync(
-          it()..emits(),
+        await check(_countingStream(1, errorAt: 0)).isRejectedByAsync(
+          (it) => it.emits(),
           actual: ['a stream with error <UnimplementedError: Error at 1>'],
           which: ['emitted an error instead of a value at:', 'fake trace'],
         );
       });
       test('can be described', () async {
-        await checkThat(it<StreamQueue<void>>()..emits())
-            .asyncDescription
-            .which(it()..deepEquals(['  emits a value']));
-        await checkThat(it<StreamQueue<int>>()..emits().which(equals(42)))
-            .asyncDescription
-            .which(it()
-              ..deepEquals([
-                '  emits a value that:',
-                '    equals <42>',
-              ]));
+        await check((Subject<StreamQueue<void>> it) => it.emits())
+            .hasAsyncDescriptionWhich(
+                (it) => it.deepEquals(['  emits a value']));
+        await check((Subject<StreamQueue<int>> it) => it.emits(equals(42)))
+            .hasAsyncDescriptionWhich((it) => it.deepEquals([
+                  '  emits a value that:',
+                  '    equals <42>',
+                ]));
       });
-      test('uses a transaction', () async {
+      test('does not consume error', () async {
         final queue = _countingStream(1, errorAt: 0);
-        await softCheckAsync<StreamQueue<int>>(queue, it()..emits());
-        await checkThat(queue).emitsError();
+        await softCheckAsync<StreamQueue<int>>(queue, (it) => it.emits());
+        await check(queue).emitsError();
       });
     });
 
     group('emitsError', () {
       test('succeeds for a stream that emits an error', () async {
-        await checkThat(_countingStream(1, errorAt: 0))
+        await check(_countingStream(1, errorAt: 0))
             .emitsError<UnimplementedError>();
       });
       test('fails for a stream that closes without emitting an error',
           () async {
-        await checkThat(_countingStream(0)).isRejectedByAsync(
-          it()..emitsError(),
+        await check(_countingStream(0)).isRejectedByAsync(
+          (it) => it.emitsError(),
           actual: ['a stream'],
           which: ['closed without emitting an expected error'],
         );
       });
       test('fails for a stream that emits value', () async {
-        await checkThat(_countingStream(1)).isRejectedByAsync(
-          it()..emitsError(),
+        await check(_countingStream(1)).isRejectedByAsync(
+          (it) => it.emitsError(),
           actual: ['a stream emitting value <0>'],
           which: ['closed without emitting an error'],
         );
       });
       test('fails for a stream that emits an error of the incorrect type',
           () async {
-        await checkThat(_countingStream(1, errorAt: 0)).isRejectedByAsync(
-          it()..emitsError<StateError>(),
+        await check(_countingStream(1, errorAt: 0)).isRejectedByAsync(
+          (it) => it.emitsError<StateError>(),
           actual: ['a stream with error <UnimplementedError: Error at 1>'],
           which: ['emitted an error which is not StateError at:', 'fake trace'],
         );
       });
       test('can be described', () async {
-        await checkThat(it<StreamQueue<void>>()..emitsError())
-            .asyncDescription
-            .which(it()..deepEquals(['  emits an error']));
-        await checkThat(it<StreamQueue<void>>()..emitsError<StateError>())
-            .asyncDescription
-            .which(it()..deepEquals(['  emits an error of type StateError']));
-        await checkThat(it<StreamQueue<void>>()
-              ..emitsError<StateError>()
-                  .which(it()..has((e) => e.message, 'message').equals('foo')))
-            .asyncDescription
-            .which(it()
-              ..deepEquals([
-                '  emits an error of type StateError that:',
-                '    has message that:',
-                '      equals \'foo\''
-              ]));
+        await check((Subject<StreamQueue<void>> it) => it.emitsError())
+            .hasAsyncDescriptionWhich(
+                (it) => it.deepEquals(['  emits an error']));
+        await check(
+                (Subject<StreamQueue<void>> it) => it.emitsError<StateError>())
+            .hasAsyncDescriptionWhich(
+                (it) => it.deepEquals(['  emits an error of type StateError']));
+        await check((Subject<StreamQueue<void>> it) => it
+              ..emitsError<StateError>(
+                  (it) => it.has((e) => e.message, 'message').equals('foo')))
+            .hasAsyncDescriptionWhich((it) => it.deepEquals([
+                  '  emits an error of type StateError that:',
+                  '    has message that:',
+                  '      equals \'foo\''
+                ]));
       });
       test('uses a transaction', () async {
         final queue = _countingStream(1);
-        await softCheckAsync<StreamQueue<int>>(queue, it()..emitsError());
-        await checkThat(queue).emits().which((equals(0)));
+        await softCheckAsync<StreamQueue<int>>(queue, (it) => it.emitsError());
+        await check(queue).emits(equals(0));
       });
     });
 
     group('emitsThrough', () {
       test('succeeds for a stream that eventuall emits a matching value',
           () async {
-        await checkThat(_countingStream(5)).emitsThrough(equals(4));
+        await check(_countingStream(5)).emitsThrough(equals(4));
       });
       test('fails for a stream that closes without emitting a matching value',
           () async {
-        await checkThat(_countingStream(4)).isRejectedByAsync(
-          it()..emitsThrough(equals(5)),
+        await check(_countingStream(4)).isRejectedByAsync(
+          (it) => it.emitsThrough(equals(5)),
           actual: ['a stream'],
           which: ['ended after emitting 4 elements with none matching'],
         );
       });
       test('can be described', () async {
-        await checkThat(it<StreamQueue<int>>()..emitsThrough(equals(42)))
-            .asyncDescription
-            .which(it()
-              ..deepEquals([
-                '  emits any values then emits a value that:',
-                '    equals <42>'
-              ]));
+        await check(
+                (Subject<StreamQueue<int>> it) => it.emitsThrough(equals(42)))
+            .hasAsyncDescriptionWhich((it) => it.deepEquals([
+                  '  emits any values then emits a value that:',
+                  '    equals <42>'
+                ]));
       });
       test('uses a transaction', () async {
         final queue = _countingStream(1);
-        await softCheckAsync(
-            queue, it<StreamQueue<int>>()..emitsThrough(equals(42)));
-        checkThat(queue).emits().which(equals(0));
+        await softCheckAsync(queue,
+            (Subject<StreamQueue<int>> it) => it.emitsThrough(equals(42)));
+        check(queue).emits(equals(0));
       });
       test('consumes events', () async {
         final queue = _countingStream(3);
-        await checkThat(queue).emitsThrough(equals(1));
-        await checkThat(queue).emits().which((equals(2)));
+        await check(queue).emitsThrough(equals(1));
+        await check(queue).emits(equals(2));
       });
     });
 
     group('emitsInOrder', () {
       test('succeeds for happy case', () async {
-        await checkThat(_countingStream(2)).inOrder([
-          it()..emits().which(equals(0)),
-          it()..emits().which((equals(1))),
-          it()..isDone(),
+        await check(_countingStream(2)).inOrder([
+          (it) => it.emits(equals(0)),
+          (it) => it.emits(equals(1)),
+          (it) => it.isDone(),
         ]);
       });
       test('reports which condition failed', () async {
-        await checkThat(_countingStream(1)).isRejectedByAsync(
-          it()..inOrder([it()..emits(), it()..emits()]),
+        await check(_countingStream(1)).isRejectedByAsync(
+          (it) => it.inOrder([(it) => it.emits(), (it) => it.emits()]),
           actual: ['a stream'],
           which: [
             'satisfied 1 conditions then',
@@ -274,8 +266,8 @@
         );
       });
       test('nestes the report for deep failures', () async {
-        await checkThat(_countingStream(2)).isRejectedByAsync(
-          it()..inOrder([it()..emits(), it()..emits().which(equals(2))]),
+        await check(_countingStream(2)).isRejectedByAsync(
+          (it) => it.inOrder([(it) => it.emits(), (it) => it.emits(equals(2))]),
           actual: ['a stream'],
           which: [
             'satisfied 1 conditions then',
@@ -288,31 +280,31 @@
         );
       });
       test('gets described with the number of conditions', () async {
-        await checkThat(it<StreamQueue<int>>()..inOrder([it(), it()]))
-            .asyncDescription
-            .which(it()..deepEquals(['  satisfies 2 conditions in order']));
+        await check(
+                (Subject<StreamQueue<int>> it) => it.inOrder([(_) {}, (_) {}]))
+            .hasAsyncDescriptionWhich(
+                (it) => it.deepEquals(['  satisfies 2 conditions in order']));
       });
       test('uses a transaction', () async {
         final queue = _countingStream(3);
         await softCheckAsync<StreamQueue<int>>(
             queue,
-            it()
-              ..inOrder([
-                it()..emits().which(equals(0)),
-                it()..emits().which(equals(1)),
-                it()..emits().which(equals(42)),
-              ]));
-        await checkThat(queue).inOrder([
-          it()..emits().which(equals(0)),
-          it()..emits().which(equals(1)),
-          it()..emits().which(equals(2)),
-          it()..isDone(),
+            (it) => it.inOrder([
+                  (it) => it.emits(equals(0)),
+                  (it) => it.emits(equals(1)),
+                  (it) => it.emits(equals(42)),
+                ]));
+        await check(queue).inOrder([
+          (it) => it.emits(equals(0)),
+          (it) => it.emits(equals(1)),
+          (it) => it.emits(equals(2)),
+          (it) => it.isDone(),
         ]);
       });
       test('consumes events', () async {
         final queue = _countingStream(3);
-        await checkThat(queue).inOrder([it()..emits(), it()..emits()]);
-        await checkThat(queue).emits().which(equals(2));
+        await check(queue).inOrder([(it) => it.emits(), (it) => it.emits()]);
+        await check(queue).emits(equals(2));
       });
     });
 
@@ -320,140 +312,134 @@
       test(
           'succeeds for a stream that closes without emitting a matching value',
           () async {
-        await checkThat(_countingStream(5)).neverEmits(equals(5));
+        await check(_countingStream(5)).neverEmits(equals(5));
       });
       test('fails for a stream that emits a matching value', () async {
-        await checkThat(_countingStream(6)).isRejectedByAsync(
-          it()..neverEmits(equals(5)),
+        await check(_countingStream(6)).isRejectedByAsync(
+          (it) => it.neverEmits(equals(5)),
           actual: ['a stream'],
           which: ['emitted <5>', 'following 5 other items'],
         );
       });
       test('can be described', () async {
-        await checkThat(it<StreamQueue<int>>()..neverEmits(equals(42)))
-            .asyncDescription
-            .which(it()
-              ..deepEquals([
-                '  never emits a value that:',
-                '    equals <42>',
-              ]));
+        await check((Subject<StreamQueue<int>> it) => it.neverEmits(equals(42)))
+            .hasAsyncDescriptionWhich((it) => it.deepEquals([
+                  '  never emits a value that:',
+                  '    equals <42>',
+                ]));
       });
       test('uses a transaction', () async {
         final queue = _countingStream(2);
         await softCheckAsync<StreamQueue<int>>(
-            queue, it()..neverEmits(equals(1)));
-        await checkThat(queue).inOrder([
-          it()..emits().which(equals(0)),
-          it()..emits().which(equals(1)),
-          it()..isDone(),
+            queue, (it) => it.neverEmits(equals(1)));
+        await check(queue).inOrder([
+          (it) => it.emits(equals(0)),
+          (it) => it.emits(equals(1)),
+          (it) => it.isDone(),
         ]);
       });
     });
 
     group('mayEmit', () {
       test('succeeds for a stream that emits a matching value', () async {
-        await checkThat(_countingStream(1)).mayEmit(equals(0));
+        await check(_countingStream(1)).mayEmit(equals(0));
       });
       test('succeeds for a stream that emits an error', () async {
-        await checkThat(_countingStream(1, errorAt: 0)).mayEmit(equals(0));
+        await check(_countingStream(1, errorAt: 0)).mayEmit(equals(0));
       });
       test('succeeds for a stream that closes', () async {
-        await checkThat(_countingStream(0)).mayEmit(equals(42));
+        await check(_countingStream(0)).mayEmit(equals(42));
       });
       test('consumes a matching event', () async {
         final queue = _countingStream(2);
-        await softCheckAsync<StreamQueue<int>>(queue, it()..mayEmit(equals(0)));
-        await checkThat(queue).emits().which(equals(1));
+        await softCheckAsync<StreamQueue<int>>(
+            queue, (it) => it.mayEmit(equals(0)));
+        await check(queue).emits(equals(1));
       });
       test('does not consume a non-matching event', () async {
         final queue = _countingStream(2);
-        await softCheckAsync<StreamQueue<int>>(queue, it()..mayEmit(equals(1)));
-        await checkThat(queue).emits().which(equals(0));
+        await softCheckAsync<StreamQueue<int>>(
+            queue, (it) => it.mayEmit(equals(1)));
+        await check(queue).emits(equals(0));
       });
       test('does not consume an error', () async {
         final queue = _countingStream(1, errorAt: 0);
-        await softCheckAsync<StreamQueue<int>>(queue, it()..mayEmit(equals(0)));
-        await checkThat(queue)
-            .emitsError<UnimplementedError>()
-            .which(it()..has((e) => e.message, 'message').equals('Error at 1'));
+        await softCheckAsync<StreamQueue<int>>(
+            queue, (it) => it.mayEmit(equals(0)));
+        await check(queue).emitsError<UnimplementedError>(
+            (it) => it.has((e) => e.message, 'message').equals('Error at 1'));
       });
     });
 
     group('mayEmitMultiple', () {
       test('succeeds for a stream that emits a matching value', () async {
-        await checkThat(_countingStream(1)).mayEmitMultiple(equals(0));
+        await check(_countingStream(1)).mayEmitMultiple(equals(0));
       });
       test('succeeds for a stream that emits an error', () async {
-        await checkThat(_countingStream(1, errorAt: 0))
-            .mayEmitMultiple(equals(0));
+        await check(_countingStream(1, errorAt: 0)).mayEmitMultiple(equals(0));
       });
       test('succeeds for a stream that closes', () async {
-        await checkThat(_countingStream(0)).mayEmitMultiple(equals(42));
+        await check(_countingStream(0)).mayEmitMultiple(equals(42));
       });
       test('consumes matching events', () async {
         final queue = _countingStream(3);
         await softCheckAsync<StreamQueue<int>>(
-            queue, it()..mayEmitMultiple(it()..isLessThan(2)));
-        await checkThat(queue).emits().which(equals(2));
+            queue, (it) => it.mayEmitMultiple((it) => it.isLessThan(2)));
+        await check(queue).emits(equals(2));
       });
       test('consumes no events if no events match', () async {
         final queue = _countingStream(2);
         await softCheckAsync<StreamQueue<int>>(
-            queue, it()..mayEmitMultiple(it()..isLessThan(0)));
-        await checkThat(queue).emits().which(equals(0));
+            queue, (it) => it.mayEmitMultiple((it) => it.isLessThan(0)));
+        await check(queue).emits(equals(0));
       });
       test('does not consume an error', () async {
         final queue = _countingStream(1, errorAt: 0);
         await softCheckAsync<StreamQueue<int>>(
-            queue, it()..mayEmitMultiple(equals(0)));
-        await checkThat(queue)
-            .emitsError<UnimplementedError>()
-            .which(it()..has((e) => e.message, 'message').equals('Error at 1'));
+            queue, (it) => it.mayEmitMultiple(equals(0)));
+        await check(queue).emitsError<UnimplementedError>(
+            (it) => it.has((e) => e.message, 'message').equals('Error at 1'));
       });
     });
 
     group('isDone', () {
       test('succeeds for an empty stream', () async {
-        await checkThat(_countingStream(0)).isDone();
+        await check(_countingStream(0)).isDone();
       });
       test('fails for a stream that emits a value', () async {
-        await checkThat(_countingStream(1)).isRejectedByAsync(it()..isDone(),
+        await check(_countingStream(1)).isRejectedByAsync((it) => it.isDone(),
             actual: ['a stream'], which: ['emitted an unexpected value: <0>']);
       });
       test('fails for a stream that emits an error', () async {
         final controller = StreamController<void>();
         controller.addError('sad', StackTrace.fromString('fake trace'));
-        await checkThat(StreamQueue(controller.stream)).isRejectedByAsync(
-            it()..isDone(),
+        await check(StreamQueue(controller.stream)).isRejectedByAsync(
+            (it) => it.isDone(),
             actual: ['a stream'],
             which: ['emitted an unexpected error: \'sad\'', 'fake trace']);
       });
       test('uses a transaction', () async {
         final queue = _countingStream(1);
-        await softCheckAsync<StreamQueue<int>>(queue, it()..isDone());
-        await checkThat(queue).emits().which(equals(0));
+        await softCheckAsync<StreamQueue<int>>(queue, (it) => it.isDone());
+        await check(queue).emits(equals(0));
       });
       test('can be described', () async {
-        await checkThat(it<StreamQueue<int>>()..isDone())
-            .asyncDescription
-            .which(it()..deepEquals(['  is done']));
+        await check((Subject<StreamQueue<int>> it) => it.isDone())
+            .hasAsyncDescriptionWhich((it) => it.deepEquals(['  is done']));
       });
     });
 
     group('emitsAnyOf', () {
       test('succeeds for a stream that matches one condition', () async {
-        await checkThat(_countingStream(1)).anyOf([
-          it()..emits().which(equals(42)),
-          it()..emits().which((equals(0)))
-        ]);
+        await check(_countingStream(1))
+            .anyOf([(it) => it.emits(equals(42)), (it) => it.emits(equals(0))]);
       });
       test('fails for a stream that matches no conditions', () async {
-        await checkThat(_countingStream(0)).isRejectedByAsync(
-            it()
-              ..anyOf([
-                it()..emits(),
-                it()..emitsThrough(equals(1)),
-              ]),
+        await check(_countingStream(0)).isRejectedByAsync(
+            (it) => it.anyOf([
+                  (it) => it.emits(),
+                  (it) => it.emitsThrough(equals(1)),
+                ]),
             actual: [
               'a stream'
             ],
@@ -466,12 +452,11 @@
             ]);
       });
       test('includes nested details for nested failures', () async {
-        await checkThat(_countingStream(1)).isRejectedByAsync(
-            it()
-              ..anyOf([
-                it()..emits().which(equals(42)),
-                it()..emitsThrough(equals(10)),
-              ]),
+        await check(_countingStream(1)).isRejectedByAsync(
+            (it) => it.anyOf([
+                  (it) => it.emits(equals(42)),
+                  (it) => it.emitsThrough(equals(10)),
+                ]),
             actual: [
               'a stream'
             ],
@@ -486,40 +471,33 @@
             ]);
       });
       test('gets described with the number of conditions', () async {
-        await checkThat(
-                it<StreamQueue<int>>()..anyOf([it()..emits(), it()..emits()]))
-            .asyncDescription
-            .which(it()..deepEquals(['  satisfies any of 2 conditions']));
+        await check((Subject<StreamQueue<int>> it) =>
+                it..anyOf([(it) => it.emits(), (it) => it.emits()]))
+            .hasAsyncDescriptionWhich(
+                (it) => it.deepEquals(['  satisfies any of 2 conditions']));
       });
       test('uses a transaction', () async {
         final queue = _countingStream(1);
         await softCheckAsync<StreamQueue<int>>(
             queue,
-            it()
-              ..anyOf([
-                it()..emits().which(equals(10)),
-                it()..emitsThrough(equals(42)),
-              ]));
-        await checkThat(queue).emits().which(equals(0));
+            (it) => it.anyOf([
+                  (it) => it.emits(equals(10)),
+                  (it) => it.emitsThrough(equals(42)),
+                ]));
+        await check(queue).emits(equals(0));
       });
       test('consumes events', () async {
         final queue = _countingStream(3);
-        await checkThat(queue).anyOf(
-            [it()..emits().which(equals(1)), it()..emitsThrough(equals(1))]);
-        await checkThat(queue).emits().which(equals(2));
+        await check(queue).anyOf(
+            [(it) => it.emits(equals(1)), (it) => it.emitsThrough(equals(1))]);
+        await check(queue).emits(equals(2));
       });
     });
   });
 
-  group('ChainAsync', () {
-    test('which', () async {
-      await checkThat(_futureSuccess()).completes().which(equals(42));
-    });
-  });
-
   group('StreamQueueWrap', () {
     test('can wrap streams in a queue', () async {
-      await checkThat(Stream.value(1)).withQueue.emits();
+      await check(Stream.value(1)).withQueue.emits();
     });
   });
 }
diff --git a/pkgs/checks/test/extensions/collection_equality_test.dart b/pkgs/checks/test/extensions/collection_equality_test.dart
index 6ab362b..3259461 100644
--- a/pkgs/checks/test/extensions/collection_equality_test.dart
+++ b/pkgs/checks/test/extensions/collection_equality_test.dart
@@ -9,7 +9,7 @@
 void main() {
   group('deepCollectionEquals', () {
     test('allows nested collections with equal elements', () {
-      checkThat(deepCollectionEquals([
+      check(deepCollectionEquals([
         'a',
         {'b': 1},
         {'c', 'd'},
@@ -27,7 +27,7 @@
     });
 
     test('allows collections inside sets', () {
-      checkThat(deepCollectionEquals({
+      check(deepCollectionEquals({
         {'a': 1}
       }, {
         {'a': 1}
@@ -35,7 +35,7 @@
     });
 
     test('allows collections as Map keys', () {
-      checkThat(deepCollectionEquals([
+      check(deepCollectionEquals([
         {
           {'a': 1}: {'b': 2}
         }
@@ -47,38 +47,45 @@
     });
 
     test('allows conditions in place of elements in lists', () {
-      checkThat(deepCollectionEquals([
+      check(deepCollectionEquals([
         'a',
         'b'
       ], [
-        it()
-          ..isA<String>().which(it()
-            ..startsWith('a')
-            ..length.isLessThan(2)),
-        it()..isA<String>().startsWith('b')
+        (Subject<dynamic> it) => it.isA<String>().which((it) => it
+          ..startsWith('a')
+          ..length.isLessThan(2)),
+        (Subject<dynamic> it) => it.isA<String>().startsWith('b')
       ])).isNull();
     });
 
     test('allows conditions in place of values in maps', () {
-      checkThat(deepCollectionEquals([
+      check(deepCollectionEquals([
         {'a': 'b'}
       ], [
-        {'a': it()..isA<String>().startsWith('b')}
+        {'a': (Subject<dynamic> it) => it.isA<String>().startsWith('b')}
       ])).isNull();
     });
 
     test('allows conditions in place of elements in sets', () {
-      checkThat(deepCollectionEquals(
-          {'b', 'a'}, {'a', it()..isA<String>().startsWith('b')})).isNull();
+      check(deepCollectionEquals({
+        'b',
+        'a'
+      }, {
+        'a',
+        (Subject<dynamic> it) => it.isA<String>().startsWith('b')
+      })).isNull();
     });
 
     test('allows conditions in place of keys in maps', () {
-      checkThat(deepCollectionEquals(
-          {'a': 'b'}, {it()..isA<String>().startsWith('a'): 'b'})).isNull();
+      check(deepCollectionEquals({
+        'a': 'b'
+      }, {
+        (Subject<dynamic> it) => it.isA<String>().startsWith('a'): 'b'
+      })).isNull();
     });
 
     test('reports non-Set elements', () {
-      checkThat(deepCollectionEquals([
+      check(deepCollectionEquals([
         ['a']
       ], [
         {'a'}
@@ -86,27 +93,28 @@
     });
 
     test('reports long iterables', () {
-      checkThat(deepCollectionEquals([0], [])).isNotNull().deepEquals([
+      check(deepCollectionEquals([0], [])).isNotNull().deepEquals([
         'has more elements than expected',
         'expected an iterable with 0 element(s)'
       ]);
     });
 
     test('reports short iterables', () {
-      checkThat(deepCollectionEquals([], [0])).isNotNull().deepEquals([
+      check(deepCollectionEquals([], [0])).isNotNull().deepEquals([
         'has too few elements',
         'expected an iterable with at least 1 element(s)'
       ]);
     });
 
     test('reports unequal elements in iterables', () {
-      checkThat(deepCollectionEquals([0], [1]))
+      check(deepCollectionEquals([0], [1]))
           .isNotNull()
           .deepEquals(['at [<0>] is <0>', 'which does not equal <1>']);
     });
 
     test('reports unmet conditions in iterables', () {
-      checkThat(deepCollectionEquals([0], [it()..isA<int>().isGreaterThan(0)]))
+      check(deepCollectionEquals(
+              [0], [(Subject<dynamic> it) => it.isA<int>().isGreaterThan(0)]))
           .isNotNull()
           .deepEquals([
         'has an element at [<0>] that:',
@@ -116,10 +124,11 @@
     });
 
     test('reports unmet conditions in map values', () {
-      checkThat(deepCollectionEquals(
-              {'a': 'b'}, {'a': it()..isA<String>().startsWith('a')}))
-          .isNotNull()
-          .deepEquals([
+      check(deepCollectionEquals({
+        'a': 'b'
+      }, {
+        'a': (Subject<dynamic> it) => it.isA<String>().startsWith('a')
+      })).isNotNull().deepEquals([
         "has no entry to match 'a': <A value that:",
         '  is a String',
         "  starts with 'a'>",
@@ -127,10 +136,11 @@
     });
 
     test('reports unmet conditions in map keys', () {
-      checkThat(deepCollectionEquals(
-              {'b': 'a'}, {it()..isA<String>().startsWith('a'): 'a'}))
-          .isNotNull()
-          .deepEquals([
+      check(deepCollectionEquals({
+        'b': 'a'
+      }, {
+        (Subject<dynamic> it) => it.isA<String>().startsWith('a'): 'a'
+      })).isNotNull().deepEquals([
         'has no entry to match <A value that:',
         '  is a String',
         "  starts with 'a'>: 'a'",
@@ -140,7 +150,7 @@
     test('reports recursive lists', () {
       var l = [];
       l.add(l);
-      checkThat(deepCollectionEquals(l, l))
+      check(deepCollectionEquals(l, l))
           .isNotNull()
           .deepEquals(['exceeds the depth limit of 1000']);
     });
@@ -148,7 +158,7 @@
     test('reports recursive sets', () {
       var s = <Object>{};
       s.add(s);
-      checkThat(deepCollectionEquals(s, s))
+      check(deepCollectionEquals(s, s))
           .isNotNull()
           .deepEquals(['exceeds the depth limit of 1000']);
     });
@@ -156,7 +166,7 @@
     test('reports maps with recursive keys', () {
       var m = <Object, Object>{};
       m[m] = 0;
-      checkThat(deepCollectionEquals(m, m))
+      check(deepCollectionEquals(m, m))
           .isNotNull()
           .deepEquals(['exceeds the depth limit of 1000']);
     });
@@ -164,7 +174,7 @@
     test('reports maps with recursive values', () {
       var m = <Object, Object>{};
       m[0] = m;
-      checkThat(deepCollectionEquals(m, m))
+      check(deepCollectionEquals(m, m))
           .isNotNull()
           .deepEquals(['exceeds the depth limit of 1000']);
     });
diff --git a/pkgs/checks/test/extensions/core_test.dart b/pkgs/checks/test/extensions/core_test.dart
index 411562e..f220e78 100644
--- a/pkgs/checks/test/extensions/core_test.dart
+++ b/pkgs/checks/test/extensions/core_test.dart
@@ -10,28 +10,33 @@
 void main() {
   group('TypeChecks', () {
     test('isA', () {
-      checkThat(1).isA<int>();
+      check(1).isA<int>();
 
-      checkThat(1).isRejectedBy(it()..isA<String>(), which: ['Is a int']);
+      check(1).isRejectedBy((it) => it.isA<String>(), which: ['Is a int']);
     });
   });
   group('HasField', () {
     test('has', () {
-      checkThat(1).has((v) => v.isOdd, 'isOdd').isTrue();
+      check(1).has((v) => v.isOdd, 'isOdd').isTrue();
 
-      checkThat(2).isRejectedBy(
-          it()..has((v) => throw UnimplementedError(), 'isOdd'),
-          which: ['threw while trying to read property']);
+      check(null).isRejectedBy(
+          (it) => it.has((v) {
+                Error.throwWithStackTrace(
+                    UnimplementedError(), StackTrace.fromString('fake trace'));
+              }, 'foo').isNotNull(),
+          which: [
+            'threw while trying to read foo: <UnimplementedError>',
+            'fake trace'
+          ]);
     });
 
     test('which', () {
-      checkThat(true).which(it()..isTrue());
+      check(true).which((it) => it.isTrue());
     });
 
     test('not', () {
-      checkThat(false).not(it()..isTrue());
-
-      checkThat(true).isRejectedBy(it()..not(it()..isTrue()), which: [
+      check(false).not((it) => it.isTrue());
+      check(true).isRejectedBy((it) => it.not((it) => it.isTrue()), which: [
         'is a value that: ',
         '    is true',
       ]);
@@ -39,12 +44,13 @@
 
     group('anyOf', () {
       test('succeeds for happy case', () {
-        checkThat(-10).anyOf([it()..isGreaterThan(1), it()..isLessThan(-1)]);
+        check(-10)
+            .anyOf([(it) => it.isGreaterThan(1), (it) => it.isLessThan(-1)]);
       });
-
       test('rejects values that do not satisfy any condition', () {
-        checkThat(0).isRejectedBy(
-            it()..anyOf([it()..isGreaterThan(1), it()..isLessThan(-1)]),
+        check(0).isRejectedBy(
+            (it) => it.anyOf(
+                [(it) => it.isGreaterThan(1), (it) => it.isLessThan(-1)]),
             which: ['did not match any condition']);
       });
     });
@@ -52,41 +58,100 @@
 
   group('BoolChecks', () {
     test('isTrue', () {
-      checkThat(true).isTrue();
+      check(true).isTrue();
 
-      checkThat(false).isRejectedBy(it()..isTrue());
+      check(false).isRejectedBy((it) => it.isTrue());
     });
 
     test('isFalse', () {
-      checkThat(false).isFalse();
+      check(false).isFalse();
 
-      checkThat(true).isRejectedBy(it()..isFalse());
+      check(true).isRejectedBy((it) => it.isFalse());
     });
   });
 
   group('EqualityChecks', () {
     test('equals', () {
-      checkThat(1).equals(1);
+      check(1).equals(1);
 
-      checkThat(1).isRejectedBy(equals(2), which: ['are not equal']);
+      check(1).isRejectedBy((it) => it.equals(2), which: ['are not equal']);
     });
     test('identical', () {
-      checkThat(1).identicalTo(1);
+      check(1).identicalTo(1);
 
-      checkThat(1)
-          .isRejectedBy(it()..identicalTo(2), which: ['is not identical']);
+      check(1)
+          .isRejectedBy((it) => it.identicalTo(2), which: ['is not identical']);
     });
   });
   group('NullabilityChecks', () {
     test('isNotNull', () {
-      checkThat(1).isNotNull();
+      check(1).isNotNull();
 
-      checkThat(null).isRejectedBy(it()..isNotNull());
+      check(null).isRejectedBy((it) => it.isNotNull());
     });
     test('isNull', () {
-      checkThat(null).isNull();
+      check(null).isNull();
 
-      checkThat(1).isRejectedBy(it()..isNull());
+      check(1).isRejectedBy((it) => it.isNull());
+    });
+  });
+
+  group('ComparableChecks on Duration', () {
+    group('isGreaterThan', () {
+      test('succeeds for greater', () {
+        check(Duration(seconds: 10)).isGreaterThan(Duration(seconds: 1));
+      });
+      test('fails for equal', () {
+        check(Duration(seconds: 10)).isRejectedBy(
+            (it) => it.isGreaterThan(Duration(seconds: 10)),
+            which: ['is not greater than <0:00:10.000000>']);
+      });
+      test('fails for less', () {
+        check(Duration(seconds: 10)).isRejectedBy(
+            (it) => it.isGreaterThan(Duration(seconds: 50)),
+            which: ['is not greater than <0:00:50.000000>']);
+      });
+    });
+    group('isGreaterOrEqual', () {
+      test('succeeds for greater', () {
+        check(Duration(seconds: 10)).isGreaterOrEqual(Duration(seconds: 1));
+      });
+      test('succeeds for equal', () {
+        check(Duration(seconds: 10)).isGreaterOrEqual(Duration(seconds: 10));
+      });
+      test('fails for less', () {
+        check(Duration(seconds: 10)).isRejectedBy(
+            (it) => it.isGreaterOrEqual(Duration(seconds: 50)),
+            which: ['is not greater than or equal to <0:00:50.000000>']);
+      });
+    });
+    group('isLessThan', () {
+      test('succeeds for less', () {
+        check(Duration(seconds: 1)).isLessThan(Duration(seconds: 10));
+      });
+      test('fails for equal', () {
+        check(Duration(seconds: 10)).isRejectedBy(
+            (it) => it.isLessThan(Duration(seconds: 10)),
+            which: ['is not less than <0:00:10.000000>']);
+      });
+      test('fails for greater', () {
+        check(Duration(seconds: 50)).isRejectedBy(
+            (it) => it.isLessThan(Duration(seconds: 10)),
+            which: ['is not less than <0:00:10.000000>']);
+      });
+    });
+    group('isLessOrEqual', () {
+      test('succeeds for less', () {
+        check(Duration(seconds: 10)).isLessOrEqual(Duration(seconds: 50));
+      });
+      test('succeeds for equal', () {
+        check(Duration(seconds: 10)).isLessOrEqual(Duration(seconds: 10));
+      });
+      test('fails for greater', () {
+        check(Duration(seconds: 10)).isRejectedBy(
+            (it) => it.isLessOrEqual(Duration(seconds: 1)),
+            which: ['is not less than or equal to <0:00:01.000000>']);
+      });
     });
   });
 }
diff --git a/pkgs/checks/test/extensions/function_test.dart b/pkgs/checks/test/extensions/function_test.dart
index c44ff1f..034d8fe 100644
--- a/pkgs/checks/test/extensions/function_test.dart
+++ b/pkgs/checks/test/extensions/function_test.dart
@@ -11,16 +11,16 @@
   group('ThrowsChecks', () {
     group('throws', () {
       test('succeeds for happy case', () {
-        checkThat(() => throw StateError('oops!')).throws<StateError>();
+        check(() => throw StateError('oops!')).throws<StateError>();
       });
       test('fails for functions that return normally', () {
-        checkThat(() {}).isRejectedBy(it()..throws<StateError>(),
+        check(() {}).isRejectedBy((it) => it.throws<StateError>(),
             actual: ['a function that returned <null>'],
             which: ['did not throw']);
       });
       test('fails for functions that throw the wrong type', () {
-        checkThat(() => throw StateError('oops!')).isRejectedBy(
-          it()..throws<ArgumentError>(),
+        check(() => throw StateError('oops!')).isRejectedBy(
+          (it) => it.throws<ArgumentError>(),
           actual: ['a function that threw error <Bad state: oops!>'],
           which: ['did not throw an ArgumentError'],
         );
@@ -29,13 +29,13 @@
 
     group('returnsNormally', () {
       test('succeeds for happy case', () {
-        checkThat(() => 1).returnsNormally().equals(1);
+        check(() => 1).returnsNormally().equals(1);
       });
       test('fails for functions that throw', () {
-        checkThat(() {
+        check(() {
           Error.throwWithStackTrace(
               StateError('oops!'), StackTrace.fromString('fake trace'));
-        }).isRejectedBy(it()..returnsNormally(),
+        }).isRejectedBy((it) => it.returnsNormally(),
             actual: ['a function that throws'],
             which: ['threw <Bad state: oops!>', 'fake trace']);
       });
diff --git a/pkgs/checks/test/extensions/iterable_test.dart b/pkgs/checks/test/extensions/iterable_test.dart
index 2081ecb..73c0881 100644
--- a/pkgs/checks/test/extensions/iterable_test.dart
+++ b/pkgs/checks/test/extensions/iterable_test.dart
@@ -11,59 +11,86 @@
 
 void main() {
   test('length', () {
-    checkThat(_testIterable).length.equals(2);
+    check(_testIterable).length.equals(2);
   });
-  test('first', () {
-    checkThat(_testIterable).first.equals(0);
+
+  group('first', () {
+    test('succeeds for happy case', () {
+      check(_testIterable).first.equals(0);
+    });
+    test('rejects empty iterable', () {
+      check([])
+          .isRejectedBy((it) => it.first.equals(0), which: ['has no elements']);
+    });
   });
-  test('last', () {
-    checkThat(_testIterable).last.equals(1);
+
+  group('last', () {
+    test('succeeds for happy case', () {
+      check(_testIterable).last.equals(1);
+    });
+    test('rejects empty iterable', () {
+      check([])
+          .isRejectedBy((it) => it.last.equals(0), which: ['has no elements']);
+    });
   });
-  test('single', () {
-    checkThat([42]).single.equals(42);
+
+  group('single', () {
+    test('succeeds for happy case', () {
+      check([42]).single.equals(42);
+    });
+    test('rejects empty iterable', () {
+      check([]).isRejectedBy((it) => it.single.equals(0),
+          which: ['has no elements']);
+    });
+    test('rejects iterable with too many elements', () {
+      check(_testIterable).isRejectedBy((it) => it.single.equals(0),
+          which: ['has more than one element']);
+    });
   });
 
   test('isEmpty', () {
-    checkThat([]).isEmpty();
-    checkThat(_testIterable)
-        .isRejectedBy(it()..isEmpty(), which: ['is not empty']);
+    check([]).isEmpty();
+    check(_testIterable)
+        .isRejectedBy((it) => it.isEmpty(), which: ['is not empty']);
   });
 
   test('isNotEmpty', () {
-    checkThat(_testIterable).isNotEmpty();
-    checkThat(Iterable<int>.empty())
-        .isRejectedBy(it()..isNotEmpty(), which: ['is not empty']);
+    check(_testIterable).isNotEmpty();
+    check(Iterable<int>.empty())
+        .isRejectedBy((it) => it.isNotEmpty(), which: ['is empty']);
   });
 
   test('contains', () {
-    checkThat(_testIterable).contains(0);
-    checkThat(_testIterable)
-        .isRejectedBy(it()..contains(2), which: ['does not contain <2>']);
+    check(_testIterable).contains(0);
+    check(_testIterable)
+        .isRejectedBy((it) => it.contains(2), which: ['does not contain <2>']);
   });
   test('any', () {
-    checkThat(_testIterable).any(equals(1));
-    checkThat(_testIterable).isRejectedBy(it()..any(equals(2)),
+    check(_testIterable).any(equals(1));
+    check(_testIterable).isRejectedBy((it) => it.any(equals(2)),
         which: ['Contains no matching element']);
   });
 
   group('containsInOrder', () {
     test('succeeds for happy case', () {
-      checkThat([0, 1, 0, 2, 0, 3]).containsInOrder([1, 2, 3]);
+      check([0, 1, 0, 2, 0, 3]).containsInOrder([1, 2, 3]);
     });
     test('can use Condition<dynamic>', () {
-      checkThat([0, 1]).containsInOrder([it()..isA<int>().isGreaterThan(0)]);
+      check([0, 1]).containsInOrder(
+          [(Subject<dynamic> it) => it.isA<int>().isGreaterThan(0)]);
     });
     test('can use Condition<T>', () {
-      checkThat([0, 1]).containsInOrder([it<int>()..isGreaterThan(0)]);
+      check([0, 1]).containsInOrder([(Subject<int> it) => it.isGreaterThan(0)]);
     });
     test('fails for not found elements by equality', () async {
-      checkThat([0]).isRejectedBy(it()..containsInOrder([1]), which: [
+      check([0]).isRejectedBy((it) => it.containsInOrder([1]), which: [
         'did not have an element matching the expectation at index 0 <1>'
       ]);
     });
     test('fails for not found elements by condition', () async {
-      checkThat([0]).isRejectedBy(
-          it()..containsInOrder([it()..isA<int>().isGreaterThan(0)]),
+      check([0]).isRejectedBy(
+          (it) => it.containsInOrder(
+              [(Subject<dynamic> it) => it.isA<int>().isGreaterThan(0)]),
           which: [
             'did not have an element matching the expectation at index 0 '
                 '<A value that:',
@@ -72,10 +99,11 @@
           ]);
     });
     test('can be described', () {
-      checkThat(it<Iterable>()..containsInOrder([1, 2, 3]))
+      check((Subject<Iterable> it) => it.containsInOrder([1, 2, 3]))
           .description
           .deepEquals(['  contains, in order: [1, 2, 3]']);
-      checkThat(it<Iterable>()..containsInOrder([1, equals(2)]))
+      check((Subject<Iterable> it) =>
+              it.containsInOrder([1, (Subject<dynamic> it) => it.equals(2)]))
           .description
           .deepEquals([
         '  contains, in order: [1,',
@@ -86,12 +114,12 @@
   });
   group('every', () {
     test('succeeds for the happy path', () {
-      checkThat(_testIterable).every(it()..isGreaterOrEqual(-1));
+      check(_testIterable).every((it) => it.isGreaterOrEqual(-1));
     });
 
     test('includes details of first failing element', () async {
-      checkThat(_testIterable)
-          .isRejectedBy(it()..every(it()..isLessThan(0)), which: [
+      check(_testIterable)
+          .isRejectedBy((it) => it.every((it) => it.isLessThan(0)), which: [
         'has an element at index 0 that:',
         '  Actual: <0>',
         '  Which: is not less than <0>',
@@ -101,12 +129,12 @@
 
   group('unorderedEquals', () {
     test('success for happy case', () {
-      checkThat(_testIterable).unorderedEquals(_testIterable.toList().reversed);
+      check(_testIterable).unorderedEquals(_testIterable.toList().reversed);
     });
 
     test('reports unmatched elements', () {
-      checkThat(_testIterable).isRejectedBy(
-          it()..unorderedEquals(_testIterable.followedBy([42, 100])),
+      check(_testIterable).isRejectedBy(
+          (it) => it.unorderedEquals(_testIterable.followedBy([42, 100])),
           which: [
             'has no element equal to the expected element at index 2: <42>',
             'or 1 other elements'
@@ -114,8 +142,8 @@
     });
 
     test('reports unexpected elements', () {
-      checkThat(_testIterable.followedBy([42, 100]))
-          .isRejectedBy(it()..unorderedEquals(_testIterable), which: [
+      check(_testIterable.followedBy([42, 100]))
+          .isRejectedBy((it) => it.unorderedEquals(_testIterable), which: [
         'has an unexpected element at index 2: <42>',
         'and 1 other unexpected elements'
       ]);
@@ -124,15 +152,14 @@
 
   group('unorderedMatches', () {
     test('success for happy case', () {
-      checkThat(_testIterable).unorderedMatches(
-          _testIterable.toList().reversed.map((i) => equals(i)));
+      check(_testIterable)
+          .unorderedMatches(_testIterable.toList().reversed.map(equals));
     });
 
     test('reports unmatched elements', () {
-      checkThat(_testIterable).isRejectedBy(
-          it()
-            ..unorderedMatches(
-                _testIterable.followedBy([42, 100]).map((i) => equals(i))),
+      check(_testIterable).isRejectedBy(
+          (it) => it.unorderedMatches(
+              _testIterable.followedBy([42, 100]).map(equals)),
           which: [
             'has no element matching the condition at index 2:',
             '  equals <42>',
@@ -141,8 +168,8 @@
     });
 
     test('reports unexpected elements', () {
-      checkThat(_testIterable.followedBy([42, 100])).isRejectedBy(
-          it()..unorderedMatches(_testIterable.map((i) => equals(i))),
+      check(_testIterable.followedBy([42, 100])).isRejectedBy(
+          (it) => it.unorderedMatches(_testIterable.map(equals)),
           which: [
             'has an unmatched element at index 2: <42>',
             'and 1 other unmatched elements'
@@ -152,14 +179,13 @@
 
   group('pairwiseComparesTo', () {
     test('succeeds for the happy path', () {
-      checkThat(_testIterable).pairwiseComparesTo(
-          [1, 2], (expected) => it()..isLessThan(expected), 'is less than');
+      check(_testIterable).pairwiseComparesTo([1, 2],
+          (expected) => (it) => it.isLessThan(expected), 'is less than');
     });
     test('fails for mismatched element', () async {
-      checkThat(_testIterable).isRejectedBy(
-          it()
-            ..pairwiseComparesTo([1, 1],
-                (expected) => it()..isLessThan(expected), 'is less than'),
+      check(_testIterable).isRejectedBy(
+          (it) => it.pairwiseComparesTo([1, 1],
+              (expected) => (it) => it.isLessThan(expected), 'is less than'),
           which: [
             'does not have an element at index 1 that:',
             '  is less than <1>',
@@ -168,19 +194,17 @@
           ]);
     });
     test('fails for too few elements', () {
-      checkThat(_testIterable).isRejectedBy(
-          it()
-            ..pairwiseComparesTo([1, 2, 3],
-                (expected) => it()..isLessThan(expected), 'is less than'),
+      check(_testIterable).isRejectedBy(
+          (it) => it.pairwiseComparesTo([1, 2, 3],
+              (expected) => (it) => it.isLessThan(expected), 'is less than'),
           which: [
             'has too few elements, there is no element to match at index 2'
           ]);
     });
     test('fails for too many elements', () {
-      checkThat(_testIterable).isRejectedBy(
-          it()
-            ..pairwiseComparesTo(
-                [1], (expected) => it()..isLessThan(expected), 'is less than'),
+      check(_testIterable).isRejectedBy(
+          (it) => it.pairwiseComparesTo([1],
+              (expected) => (it) => it.isLessThan(expected), 'is less than'),
           which: ['has too many elements, expected exactly 1']);
     });
   });
diff --git a/pkgs/checks/test/extensions/map_test.dart b/pkgs/checks/test/extensions/map_test.dart
index 0aaef0d..1b2684c 100644
--- a/pkgs/checks/test/extensions/map_test.dart
+++ b/pkgs/checks/test/extensions/map_test.dart
@@ -14,61 +14,104 @@
 
 void main() {
   test('length', () {
-    checkThat(_testMap).length.equals(2);
+    check(_testMap).length.equals(2);
   });
   test('entries', () {
-    checkThat(_testMap).entries.any(
-          it()
+    check(_testMap).entries.any(
+          (it) => it
             ..has((p0) => p0.key, 'key').equals('a')
             ..has((p0) => p0.value, 'value').equals(1),
         );
   });
   test('keys', () {
-    checkThat(_testMap).keys.contains('a');
+    check(_testMap).keys.contains('a');
   });
   test('values', () {
-    checkThat(_testMap).values.contains(1);
+    check(_testMap).values.contains(1);
   });
 
-  test('operator []', () async {
-    checkThat(_testMap)['a'].equals(1);
-    checkThat(_testMap)
-        .isRejectedBy(it()..['z'], which: ['does not contain the key \'z\'']);
+  group('operator []', () {
+    test('succeeds for a key that exists', () {
+      check(_testMap)['a'].equals(1);
+    });
+    test('fails for a missing key', () {
+      check(_testMap).isRejectedBy((it) => it['z'],
+          which: ["does not contain the key 'z'"]);
+    });
+    test('can be described', () {
+      check((Subject<Map<String, Object>> it) => it['some\nlong\nkey'])
+          .description
+          .deepEquals([
+        "  contains a value for 'some",
+        '  long',
+        "  key'",
+      ]);
+      check((Subject<Map<String, Object>> it) =>
+          it['some\nlong\nkey'].equals(1)).description.deepEquals([
+        "  contains a value for 'some",
+        '  long',
+        "  key' that:",
+        '    equals <1>',
+      ]);
+    });
   });
   test('isEmpty', () {
-    checkThat(<String, int>{}).isEmpty();
-    checkThat(_testMap).isRejectedBy(it()..isEmpty(), which: ['is not empty']);
+    check(<String, int>{}).isEmpty();
+    check(_testMap).isRejectedBy((it) => it.isEmpty(), which: ['is not empty']);
   });
   test('isNotEmpty', () {
-    checkThat(_testMap).isNotEmpty();
-    checkThat({}).isRejectedBy(it()..isNotEmpty(), which: ['is not empty']);
+    check(_testMap).isNotEmpty();
+    check({}).isRejectedBy((it) => it.isNotEmpty(), which: ['is not empty']);
   });
-  test('containsKey', () {
-    checkThat(_testMap).containsKey('a');
-
-    checkThat(_testMap).isRejectedBy(
-      it()..containsKey('c'),
-      which: ["does not contain key 'c'"],
-    );
+  group('containsKey', () {
+    test('succeeds for a key that exists', () {
+      check(_testMap).containsKey('a');
+    });
+    test('fails for a missing key', () {
+      check(_testMap).isRejectedBy(
+        (it) => it.containsKey('c'),
+        which: ["does not contain key 'c'"],
+      );
+    });
+    test('can be described', () {
+      check((Subject<Map<String, Object>> it) =>
+          it.containsKey('some\nlong\nkey')).description.deepEquals([
+        "  contains key 'some",
+        '  long',
+        "  key'",
+      ]);
+    });
   });
   test('containsKeyThat', () {
-    checkThat(_testMap).containsKeyThat(equals('a'));
-    checkThat(_testMap).isRejectedBy(
-      it()..containsKeyThat(equals('c')),
+    check(_testMap).containsKeyThat(equals('a'));
+    check(_testMap).isRejectedBy(
+      (it) => it.containsKeyThat(equals('c')),
       which: ['Contains no matching key'],
     );
   });
-  test('containsValue', () {
-    checkThat(_testMap).containsValue(1);
-    checkThat(_testMap).isRejectedBy(
-      it()..containsValue(3),
-      which: ['does not contain value <3>'],
-    );
+  group('containsValue', () {
+    test('succeeds for happy case', () {
+      check(_testMap).containsValue(1);
+    });
+    test('fails for missing value', () {
+      check(_testMap).isRejectedBy(
+        (it) => it.containsValue(3),
+        which: ['does not contain value <3>'],
+      );
+    });
+    test('can be described', () {
+      check((Subject<Map<String, String>> it) =>
+          it.containsValue('some\nlong\nkey')).description.deepEquals([
+        "  contains value 'some",
+        '  long',
+        "  key'",
+      ]);
+    });
   });
   test('containsValueThat', () {
-    checkThat(_testMap).containsValueThat(equals(1));
-    checkThat(_testMap).isRejectedBy(
-      it()..containsValueThat(equals(3)),
+    check(_testMap).containsValueThat(equals(1));
+    check(_testMap).isRejectedBy(
+      (it) => it.containsValueThat(equals(3)),
       which: ['Contains no matching value'],
     );
   });
diff --git a/pkgs/checks/test/extensions/math_test.dart b/pkgs/checks/test/extensions/math_test.dart
index 131cfa6..0f346d3 100644
--- a/pkgs/checks/test/extensions/math_test.dart
+++ b/pkgs/checks/test/extensions/math_test.dart
@@ -9,194 +9,140 @@
 
 void main() {
   group('num checks', () {
-    group('greater than', () {
-      test('succeeds for happy case', () {
-        checkThat(42).isGreaterThan(7);
-      });
-      test('fails for less than', () {
-        checkThat(42).isRejectedBy(it()..isGreaterThan(50),
-            which: ['is not greater than <50>']);
-      });
-      test('fails for equal', () {
-        checkThat(42).isRejectedBy(it()..isGreaterThan(42),
-            which: ['is not greater than <42>']);
-      });
-    });
-
-    group('greater than or equal', () {
-      test('succeeds for happy case', () {
-        checkThat(42).isGreaterOrEqual(7);
-      });
-      test('fails for less than', () {
-        checkThat(42).isRejectedBy(it()..isGreaterOrEqual(50),
-            which: ['is not greater than or equal to <50>']);
-      });
-      test('succeeds for equal', () {
-        checkThat(42).isGreaterOrEqual(42);
-      });
-    });
-
-    group('less than', () {
-      test('succeeds for happy case', () {
-        checkThat(42).isLessThan(50);
-      });
-      test('fails for greater than', () {
-        checkThat(42)
-            .isRejectedBy(it()..isLessThan(7), which: ['is not less than <7>']);
-      });
-      test('fails for equal', () {
-        checkThat(42).isRejectedBy(it()..isLessThan(42),
-            which: ['is not less than <42>']);
-      });
-    });
-
-    group('less than or equal', () {
-      test('succeeds for happy case', () {
-        checkThat(42).isLessOrEqual(50);
-      });
-      test('fails for greater than', () {
-        checkThat(42).isRejectedBy(it()..isLessOrEqual(7),
-            which: ['is not less than or equal to <7>']);
-      });
-      test('succeeds for equal', () {
-        checkThat(42).isLessOrEqual(42);
-      });
-    });
-
     group('isNaN', () {
       test('succeeds for happy case', () {
-        checkThat(double.nan).isNaN();
+        check(double.nan).isNaN();
       });
       test('fails for ints', () {
-        checkThat(42).isRejectedBy(it()..isNaN(), which: ['is a number']);
+        check(42).isRejectedBy((it) => it.isNaN(), which: ['is a number']);
       });
       test('fails for numeric doubles', () {
-        checkThat(42.1).isRejectedBy(it()..isNaN(), which: ['is a number']);
+        check(42.1).isRejectedBy((it) => it.isNaN(), which: ['is a number']);
       });
     });
 
     group('isNotNan', () {
       test('succeeds for ints', () {
-        checkThat(42).isNotNaN();
+        check(42).isNotNaN();
       });
       test('succeeds numeric doubles', () {
-        checkThat(42.1).isNotNaN();
+        check(42.1).isNotNaN();
       });
       test('fails for NaN', () {
-        checkThat(double.nan)
-            .isRejectedBy(it()..isNotNaN(), which: ['is not a number (NaN)']);
+        check(double.nan).isRejectedBy((it) => it.isNotNaN(),
+            which: ['is not a number (NaN)']);
       });
     });
     group('isNegative', () {
       test('succeeds for negative ints', () {
-        checkThat(-1).isNegative();
+        check(-1).isNegative();
       });
       test('succeeds for -0.0', () {
-        checkThat(-0.0).isNegative();
+        check(-0.0).isNegative();
       });
       test('fails for zero', () {
-        checkThat(0)
-            .isRejectedBy(it()..isNegative(), which: ['is not negative']);
+        check(0)
+            .isRejectedBy((it) => it.isNegative(), which: ['is not negative']);
       });
     });
     group('isNotNegative', () {
       test('succeeds for positive ints', () {
-        checkThat(1).isNotNegative();
+        check(1).isNotNegative();
       });
       test('succeeds for 0', () {
-        checkThat(0).isNotNegative();
+        check(0).isNotNegative();
       });
       test('fails for -0.0', () {
-        checkThat(-0.0)
-            .isRejectedBy(it()..isNotNegative(), which: ['is negative']);
+        check(-0.0)
+            .isRejectedBy((it) => it.isNotNegative(), which: ['is negative']);
       });
       test('fails for negative numbers', () {
-        checkThat(-1)
-            .isRejectedBy(it()..isNotNegative(), which: ['is negative']);
+        check(-1)
+            .isRejectedBy((it) => it.isNotNegative(), which: ['is negative']);
       });
     });
 
     group('isFinite', () {
       test('succeeds for finite numbers', () {
-        checkThat(1).isFinite();
+        check(1).isFinite();
       });
       test('fails for NaN', () {
-        checkThat(double.nan)
-            .isRejectedBy(it()..isFinite(), which: ['is not finite']);
+        check(double.nan)
+            .isRejectedBy((it) => it.isFinite(), which: ['is not finite']);
       });
       test('fails for infinity', () {
-        checkThat(double.infinity)
-            .isRejectedBy(it()..isFinite(), which: ['is not finite']);
+        check(double.infinity)
+            .isRejectedBy((it) => it.isFinite(), which: ['is not finite']);
       });
       test('fails for negative infinity', () {
-        checkThat(double.negativeInfinity)
-            .isRejectedBy(it()..isFinite(), which: ['is not finite']);
+        check(double.negativeInfinity)
+            .isRejectedBy((it) => it.isFinite(), which: ['is not finite']);
       });
     });
     group('isNotFinite', () {
       test('succeeds for infinity', () {
-        checkThat(double.infinity).isNotFinite();
+        check(double.infinity).isNotFinite();
       });
       test('succeeds for negative infinity', () {
-        checkThat(double.negativeInfinity).isNotFinite();
+        check(double.negativeInfinity).isNotFinite();
       });
       test('succeeds for NaN', () {
-        checkThat(double.nan).isNotFinite();
+        check(double.nan).isNotFinite();
       });
       test('fails for finite numbers', () {
-        checkThat(1).isRejectedBy(it()..isNotFinite(), which: ['is finite']);
+        check(1).isRejectedBy((it) => it.isNotFinite(), which: ['is finite']);
       });
     });
     group('isInfinite', () {
       test('succeeds for infinity', () {
-        checkThat(double.infinity).isInfinite();
+        check(double.infinity).isInfinite();
       });
       test('succeeds for negative infinity', () {
-        checkThat(double.negativeInfinity).isInfinite();
+        check(double.negativeInfinity).isInfinite();
       });
       test('fails for NaN', () {
-        checkThat(double.nan)
-            .isRejectedBy(it()..isInfinite(), which: ['is not infinite']);
+        check(double.nan)
+            .isRejectedBy((it) => it.isInfinite(), which: ['is not infinite']);
       });
       test('fails for finite numbers', () {
-        checkThat(1)
-            .isRejectedBy(it()..isInfinite(), which: ['is not infinite']);
+        check(1)
+            .isRejectedBy((it) => it.isInfinite(), which: ['is not infinite']);
       });
     });
 
     group('isNotInfinite', () {
       test('succeeds for finite numbers', () {
-        checkThat(1).isNotInfinite();
+        check(1).isNotInfinite();
       });
       test('succeeds for NaN', () {
-        checkThat(double.nan).isNotInfinite();
+        check(double.nan).isNotInfinite();
       });
       test('fails for infinity', () {
-        checkThat(double.infinity)
-            .isRejectedBy(it()..isNotInfinite(), which: ['is infinite']);
+        check(double.infinity)
+            .isRejectedBy((it) => it.isNotInfinite(), which: ['is infinite']);
       });
       test('fails for negative infinity', () {
-        checkThat(double.negativeInfinity)
-            .isRejectedBy(it()..isNotInfinite(), which: ['is infinite']);
+        check(double.negativeInfinity)
+            .isRejectedBy((it) => it.isNotInfinite(), which: ['is infinite']);
       });
     });
     group('closeTo', () {
       test('succeeds for equal numbers', () {
-        checkThat(1).isCloseTo(1, 1);
+        check(1).isCloseTo(1, 1);
       });
       test('succeeds at less than delta away', () {
-        checkThat(1).isCloseTo(2, 2);
+        check(1).isCloseTo(2, 2);
       });
       test('succeeds at exactly delta away', () {
-        checkThat(1).isCloseTo(2, 1);
+        check(1).isCloseTo(2, 1);
       });
       test('fails for low values', () {
-        checkThat(1)
-            .isRejectedBy(it()..isCloseTo(3, 1), which: ['differs by <2>']);
+        check(1).isRejectedBy((it) => it.isCloseTo(3, 1),
+            which: ['differs by <2>']);
       });
       test('fails for high values', () {
-        checkThat(5)
-            .isRejectedBy(it()..isCloseTo(3, 1), which: ['differs by <2>']);
+        check(5).isRejectedBy((it) => it.isCloseTo(3, 1),
+            which: ['differs by <2>']);
       });
     });
   });
diff --git a/pkgs/checks/test/extensions/string_test.dart b/pkgs/checks/test/extensions/string_test.dart
index 7327f9c..2b651f1 100644
--- a/pkgs/checks/test/extensions/string_test.dart
+++ b/pkgs/checks/test/extensions/string_test.dart
@@ -10,58 +10,70 @@
 void main() {
   group('StringChecks', () {
     test('contains', () {
-      checkThat('bob').contains('bo');
-      checkThat('bob').isRejectedBy(it()..contains('kayleb'),
+      check('bob').contains('bo');
+      check('bob').isRejectedBy((it) => it.contains('kayleb'),
           which: ["Does not contain 'kayleb'"]);
     });
     test('length', () {
-      checkThat('bob').length.equals(3);
+      check('bob').length.equals(3);
     });
     test('isEmpty', () {
-      checkThat('').isEmpty();
-      checkThat('bob').isRejectedBy(it()..isEmpty(), which: ['is not empty']);
+      check('').isEmpty();
+      check('bob').isRejectedBy((it) => it.isEmpty(), which: ['is not empty']);
     });
     test('isNotEmpty', () {
-      checkThat('bob').isNotEmpty();
-      checkThat('').isRejectedBy(it()..isNotEmpty(), which: ['is empty']);
+      check('bob').isNotEmpty();
+      check('').isRejectedBy((it) => it.isNotEmpty(), which: ['is empty']);
     });
     test('startsWith', () {
-      checkThat('bob').startsWith('bo');
-      checkThat('bob').isRejectedBy(it()..startsWith('kayleb'),
+      check('bob').startsWith('bo');
+      check('bob').isRejectedBy((it) => it.startsWith('kayleb'),
           which: ["does not start with 'kayleb'"]);
     });
     test('endsWith', () {
-      checkThat('bob').endsWith('ob');
-      checkThat('bob').isRejectedBy(it()..endsWith('kayleb'),
+      check('bob').endsWith('ob');
+      check('bob').isRejectedBy((it) => it.endsWith('kayleb'),
           which: ["does not end with 'kayleb'"]);
     });
 
     group('matches', () {
-      test('succeeds for strings that match', () {
-        checkThat('123').matches(RegExp(r'\d\d\d'));
+      test('succeeds for strings that match a regex', () {
+        check('123').matchesPattern(RegExp(r'\d\d\d'));
       });
-      test('fails for non-matching strings', () {
-        checkThat('abc').isRejectedBy(it()..matches(RegExp(r'\d\d\d')),
+      test('succeeds for strings that match a string pattern', () {
+        check(r'\d').matchesPattern(r'\d');
+      });
+      test('fails for non-matching regex', () {
+        check('abc').isRejectedBy((it) => it.matchesPattern(RegExp(r'\d\d\d')),
             which: [r'does not match <RegExp: pattern=\d\d\d flags=>']);
       });
+      test('fails for non-matching string pattern', () {
+        // A string is _not_ converted to a regex, string patterns must match
+        // directly.
+        check('123').isRejectedBy((it) => it.matchesPattern(r'\d\d\d'),
+            which: [r"does not match '\\d\\d\\d'"]);
+      });
       test('can be described', () {
-        checkThat(it<String>()..matches(RegExp(r'\d\d\d')))
+        check((Subject<String> it) => it.matchesPattern(RegExp(r'\d\d\d')))
             .description
             .deepEquals([r'  matches <RegExp: pattern=\d\d\d flags=>']);
+        check((Subject<String> it) => it.matchesPattern('abc'))
+            .description
+            .deepEquals([r"  matches 'abc'"]);
       });
     });
 
     group('containsInOrder', () {
       test('happy case', () {
-        checkThat('foo bar baz').containsInOrder(['foo', 'baz']);
+        check('foo bar baz').containsInOrder(['foo', 'baz']);
       });
       test('reports when first substring is missing', () {
-        checkThat('baz').isRejectedBy(it()..containsInOrder(['foo', 'baz']),
+        check('baz').isRejectedBy((it) => it.containsInOrder(['foo', 'baz']),
             which: ['does not have a match for the substring \'foo\'']);
       });
       test('reports when substring is missing following a match', () {
-        checkThat('foo bar')
-            .isRejectedBy(it()..containsInOrder(['foo', 'baz']), which: [
+        check('foo bar')
+            .isRejectedBy((it) => it.containsInOrder(['foo', 'baz']), which: [
           'does not have a match for the substring \'baz\'',
           'following the other matches up to character 3'
         ]);
@@ -70,42 +82,44 @@
 
     group('equals', () {
       test('succeeeds for happy case', () {
-        checkThat('foo').equals('foo');
+        check('foo').equals('foo');
       });
       test('succeeeds for equal empty strings', () {
-        checkThat('').equals('');
+        check('').equals('');
       });
       test('reports extra characters for long string', () {
-        checkThat('foobar').isRejectedBy(equals('foo'),
+        check('foobar').isRejectedBy((it) => it.equals('foo'),
             which: ['is too long with unexpected trailing characters:', 'bar']);
       });
       test('reports extra characters for long string against empty', () {
-        checkThat('foo')
-            .isRejectedBy(equals(''), which: ['is not the empty string']);
+        check('foo').isRejectedBy((it) => it.equals(''),
+            which: ['is not the empty string']);
       });
       test('reports truncated extra characters for very long string', () {
-        checkThat('foobar baz more stuff').isRejectedBy(equals('foo'), which: [
-          'is too long with unexpected trailing characters:',
-          'bar baz mo ...'
-        ]);
+        check('foobar baz more stuff').isRejectedBy((it) => it.equals('foo'),
+            which: [
+              'is too long with unexpected trailing characters:',
+              'bar baz mo ...'
+            ]);
       });
       test('reports missing characters for short string', () {
-        checkThat('foo').isRejectedBy(equals('foobar'),
+        check('foo').isRejectedBy((it) => it.equals('foobar'),
             which: ['is too short with missing trailing characters:', 'bar']);
       });
       test('reports missing characters for empty string', () {
-        checkThat('').isRejectedBy(equals('foo bar baz'),
+        check('').isRejectedBy((it) => it.equals('foo bar baz'),
             actual: ['an empty string'],
             which: ['is missing all expected characters:', 'foo bar ba ...']);
       });
       test('reports truncated missing characters for very short string', () {
-        checkThat('foo').isRejectedBy(equals('foobar baz more stuff'), which: [
-          'is too short with missing trailing characters:',
-          'bar baz mo ...'
-        ]);
+        check('foo').isRejectedBy((it) => it.equals('foobar baz more stuff'),
+            which: [
+              'is too short with missing trailing characters:',
+              'bar baz mo ...'
+            ]);
       });
       test('reports index of different character', () {
-        checkThat('hit').isRejectedBy(equals('hat'), which: [
+        check('hit').isRejectedBy((it) => it.equals('hat'), which: [
           'differs at offset 1:',
           'hat',
           'hit',
@@ -114,31 +128,32 @@
       });
       test('reports truncated index of different character in large string',
           () {
-        checkThat('blah blah blah hit blah blah blah')
-            .isRejectedBy(equals('blah blah blah hat blah blah blah'), which: [
-          'differs at offset 16:',
-          '... lah blah hat blah bl ...',
-          '... lah blah hit blah bl ...',
-          '              ^',
-        ]);
+        check('blah blah blah hit blah blah blah').isRejectedBy(
+            (it) => it.equals('blah blah blah hat blah blah blah'),
+            which: [
+              'differs at offset 16:',
+              '... lah blah hat blah bl ...',
+              '... lah blah hit blah bl ...',
+              '              ^',
+            ]);
       });
     });
 
     group('equalsIgnoringCase', () {
       test('succeeeds for happy case', () {
-        checkThat('FOO').equalsIgnoringCase('foo');
-        checkThat('foo').equalsIgnoringCase('FOO');
+        check('FOO').equalsIgnoringCase('foo');
+        check('foo').equalsIgnoringCase('FOO');
       });
       test('reports original extra characters for long string', () {
-        checkThat('FOOBAR').isRejectedBy(it()..equalsIgnoringCase('foo'),
+        check('FOOBAR').isRejectedBy((it) => it.equalsIgnoringCase('foo'),
             which: ['is too long with unexpected trailing characters:', 'BAR']);
       });
       test('reports original missing characters for short string', () {
-        checkThat('FOO').isRejectedBy(it()..equalsIgnoringCase('fooBAR'),
+        check('FOO').isRejectedBy((it) => it.equalsIgnoringCase('fooBAR'),
             which: ['is too short with missing trailing characters:', 'BAR']);
       });
       test('reports index of different character with original characters', () {
-        checkThat('HiT').isRejectedBy(it()..equalsIgnoringCase('hAt'), which: [
+        check('HiT').isRejectedBy((it) => it.equalsIgnoringCase('hAt'), which: [
           'differs at offset 1:',
           'hAt',
           'HiT',
@@ -149,34 +164,36 @@
 
     group('equalsIgnoringWhitespace', () {
       test('allows differing internal whitespace', () {
-        checkThat('foo \t\n bar').equalsIgnoringWhitespace('foo bar');
+        check('foo \t\n bar').equalsIgnoringWhitespace('foo bar');
       });
       test('allows extra leading/trailing whitespace', () {
-        checkThat(' foo ').equalsIgnoringWhitespace('foo');
+        check(' foo ').equalsIgnoringWhitespace('foo');
       });
       test('allows missing leading/trailing whitespace', () {
-        checkThat('foo').equalsIgnoringWhitespace(' foo ');
+        check('foo').equalsIgnoringWhitespace(' foo ');
       });
       test('reports original extra characters for long string', () {
-        checkThat('foo \t bar \n baz')
-            .isRejectedBy(it()..equalsIgnoringWhitespace('foo bar'), which: [
-          'is too long with unexpected trailing characters:',
-          ' baz'
-        ]);
+        check('foo \t bar \n baz').isRejectedBy(
+            (it) => it.equalsIgnoringWhitespace('foo bar'),
+            which: [
+              'is too long with unexpected trailing characters:',
+              ' baz'
+            ]);
       });
       test('reports original missing characters for short string', () {
-        checkThat('foo  bar').isRejectedBy(
-            it()..equalsIgnoringWhitespace('foo bar baz'),
+        check('foo  bar').isRejectedBy(
+            (it) => it.equalsIgnoringWhitespace('foo bar baz'),
             which: ['is too short with missing trailing characters:', ' baz']);
       });
       test('reports index of different character with original characters', () {
-        checkThat('x  hit  x')
-            .isRejectedBy(it()..equalsIgnoringWhitespace('x hat x'), which: [
-          'differs at offset 3:',
-          'x hat x',
-          'x hit x',
-          '   ^',
-        ]);
+        check('x  hit  x').isRejectedBy(
+            (it) => it.equalsIgnoringWhitespace('x hat x'),
+            which: [
+              'differs at offset 3:',
+              'x hat x',
+              'x hit x',
+              '   ^',
+            ]);
       });
     });
   });
diff --git a/pkgs/checks/test/failure_message_test.dart b/pkgs/checks/test/failure_message_test.dart
index 0c6fbb7..217d287 100644
--- a/pkgs/checks/test/failure_message_test.dart
+++ b/pkgs/checks/test/failure_message_test.dart
@@ -5,8 +5,8 @@
 void main() {
   group('failures', () {
     test('includes expected, actual, and which', () {
-      checkThat(() {
-        checkThat(1).isGreaterThan(2);
+      check(() {
+        check(1).isGreaterThan(2);
       }).throwsFailure().equals('''
 Expected: a int that:
   is greater than <2>
@@ -15,8 +15,8 @@
     });
 
     test('includes matching portions of actual', () {
-      checkThat(() {
-        checkThat([]).length.equals(1);
+      check(() {
+        check([]).length.equals(1);
       }).throwsFailure().equals('''
 Expected: a List<dynamic> that:
   has length that:
@@ -28,20 +28,20 @@
     });
 
     test('include a reason when provided', () {
-      checkThat(() {
-        checkThat(because: 'Some reason', 1).isGreaterThan(2);
+      check(() {
+        check(because: 'Some reason', 1).isGreaterThan(2);
       }).throwsFailure().endsWith('Reason: Some reason');
     });
 
     test('retain type label following isNotNull', () {
-      checkThat(() {
-        checkThat<int?>(1).isNotNull().isGreaterThan(2);
+      check(() {
+        check<int?>(1).isNotNull().isGreaterThan(2);
       }).throwsFailure().startsWith('Expected: a int? that:\n');
     });
 
     test('retain reason following isNotNull', () {
-      checkThat(() {
-        checkThat<int?>(because: 'Some reason', 1).isNotNull().isGreaterThan(2);
+      check(() {
+        check<int?>(because: 'Some reason', 1).isNotNull().isGreaterThan(2);
       }).throwsFailure().endsWith('Reason: Some reason');
     });
   });
diff --git a/pkgs/checks/test/soft_check_test.dart b/pkgs/checks/test/soft_check_test.dart
new file mode 100644
index 0000000..87c9b27
--- /dev/null
+++ b/pkgs/checks/test/soft_check_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:checks/checks.dart';
+import 'package:test/scaffolding.dart';
+
+import 'test_shared.dart';
+
+void main() {
+  group('softCheck', () {
+    test('returns the first failure', () {
+      check(0).isRejectedBy(
+          (it) => it
+            ..isGreaterThan(1)
+            ..isGreaterThan(2),
+          which: ['is not greater than <1>']);
+    });
+  });
+  group('softCheckAsync', () {
+    test('returns the first failure', () async {
+      check(Future.value(0)).isRejectedByAsync(
+          (it) => it
+            ..completes((it) => it.isGreaterThan(1))
+            ..completes((it) => it.isGreaterThan(2)),
+          actual: ['<0>'],
+          which: ['is not greater than <1>']);
+    });
+  });
+}
diff --git a/pkgs/checks/test/test_shared.dart b/pkgs/checks/test/test_shared.dart
index 325c632..87401ca 100644
--- a/pkgs/checks/test/test_shared.dart
+++ b/pkgs/checks/test/test_shared.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:async';
+
 import 'package:checks/checks.dart';
 import 'package:checks/context.dart';
 
@@ -10,8 +12,8 @@
       {Iterable<String>? actual, Iterable<String>? which}) {
     late T actualValue;
     var didRunCallback = false;
-    final rejection = context
-        .nest<Rejection>('does not meet a condition with a Rejection', (value) {
+    final rejection = context.nest<Rejection>(
+        () => ['does not meet a condition with a Rejection'], (value) {
       actualValue = value;
       didRunCallback = true;
       final failure = softCheck(value, condition);
@@ -44,8 +46,9 @@
       {Iterable<String>? actual, Iterable<String>? which}) async {
     late T actualValue;
     var didRunCallback = false;
-    final rejection = (await context.nestAsync<Rejection>(
-        'does not meet an async condition with a Rejection', (value) async {
+    await context.nestAsync<Rejection>(
+        () => ['does not meet an async condition with a Rejection'],
+        (value) async {
       actualValue = value;
       didRunCallback = true;
       final failure = await softCheckAsync(value, condition);
@@ -56,31 +59,34 @@
         ]);
       }
       return Extracted.value(failure.rejection);
-    }));
-    if (didRunCallback) {
-      rejection
-          .has((r) => r.actual, 'actual')
-          .deepEquals(actual ?? literal(actualValue));
-    } else {
-      rejection
-          .has((r) => r.actual, 'actual')
-          .context
-          .expect(() => ['is left default'], (_) => null);
-    }
-    if (which == null) {
-      rejection.has((r) => r.which, 'which').isNull();
-    } else {
-      rejection.has((r) => r.which, 'which').isNotNull().deepEquals(which);
-    }
+    }, (rejection) {
+      if (didRunCallback) {
+        rejection
+            .has((r) => r.actual, 'actual')
+            .deepEquals(actual ?? literal(actualValue));
+      } else {
+        rejection
+            .has((r) => r.actual, 'actual')
+            .context
+            .expect(() => ['is left default'], (_) => null);
+      }
+      if (which == null) {
+        rejection.has((r) => r.which, 'which').isNull();
+      } else {
+        rejection.has((r) => r.which, 'which').isNotNull().deepEquals(which);
+      }
+    });
   }
 }
 
 extension ConditionChecks<T> on Subject<Condition<T>> {
   Subject<Iterable<String>> get description =>
       has((c) => describe<T>(c), 'description');
-  Future<Subject<Iterable<String>>> get asyncDescription async =>
+  Future<void> hasAsyncDescriptionWhich(
+          Condition<Iterable<String>> descriptionCondition) =>
       context.nestAsync(
-          'has description',
+          () => ['has description'],
           (condition) async =>
-              Extracted.value(await describeAsync<T>(condition)));
+              Extracted.value(await describeAsync<T>(condition)),
+          descriptionCondition);
 }
diff --git a/pkgs/test/CHANGELOG.md b/pkgs/test/CHANGELOG.md
index 2a5651c..8e3b429 100644
--- a/pkgs/test/CHANGELOG.md
+++ b/pkgs/test/CHANGELOG.md
@@ -1,9 +1,86 @@
-## 1.23.0-dev
+## 1.24.7-wip
+
+* Simplify the initialization of the per-suite message channel within browser
+  tests. See https://github.com/dart-lang/test/issues/2065
+* Add a timeout to browser test suite loads.
+
+## 1.24.6
+
+* Fix communication failures between minified test apps and the non-minified
+  host app.
+* Add support for discontinuing after the first failing test with `--fail-fast`.
+
+## 1.24.5
+
+* Change `compiling <path>` to `loading <path>` message in all cases. Surface
+  the "loading" messages in the situations where previously only the
+  "compiling" message would be used.
+* Support browser tests where the frame creates the message channel.
+
+## 1.24.4
+
+* Drop support for null unsafe Dart, bump SDK constraint to `3.0.0`.
+* Make some annotation classes `final`: `OnPlatform`, `Retry`, `Skip`, `Tags`,
+  `TestOn`, `Timeout`.
+* Fix the `root_` fields in the JSON reporter when running a test on Windows
+  with an absolute path.
+* Add support for `SAFARI_EXECUTABLE`, `FIREFOX_EXECUTABLE` and
+  `MS_EDGE_EXECUTABLE` for custom browser installations.
+* Allow the latest analyzer (6.x.x).
+* Add `MOZ_AUTOMATION=1` environmental variable to Firefox runner, to make
+  launcher process on Windows wait for browser exit.
+
+## 1.24.3
+
+* Fix compatibility with wasm number semantics.
+
+## 1.24.2
+
+* Copy an existing nonce from a script on the test HTML page to the script
+  created by the test runner host javascript. This only impacts environments
+  testing with custom HTML that includes a nonce.
+* Support the Microsoft Edge browser (use the `edge` platform in your test
+  configuration file or `-p edge` on the command line).
+
+## 1.24.1
+
+* Handle a missing `'compiler'` value when running a test compiled against a
+  newer `test_api` than the runner back end is using. The expectation was that
+  the json protocol is only used across packages compatible with the same major
+  version of the `test_api` package, but `flutter test` does not check the
+  version of packages in the pub solve for user test code.
+
+## 1.24.0
+
+* Support the `--compiler` flag, which can be used to configure which compiler
+  to use.
+  * To specify a compiler by platform, the argument supports platform selectors
+    through this syntax `[<platform>:]<compiler>`. For example the command line
+    argument `--compiler vm:source` would run all vm tests from source instead
+    of compiling to kernel first.
+  * If no given compiler is compatible for a platform, it will use its default
+    compiler instead.
+* Add support for running tests as native executables (vm platform only).
+  * You can run tests this way with `--compiler exe`.
+* Support compiler identifiers in platform selectors.
+* List the supported compilers for each platform in the usage text.
+* Update all reporters to print the compiler along with the platform name
+  when configured to print the platform. Extend the logic for printing platofrm
+  information to do so if any compilers are explicitly configured.
+* Deprecate `--use-data-isolate-strategy`. It is now an alias for `-c vm:source`
+  which is roughly equivalent. If this is breaking for you please file an issue.
+
+## 1.23.1
+
+* Fix running paths by absolute path (with drive letter) on windows.
+
+## 1.23.0
 
 * Avoid empty expandable groups for tests without extra output in Github
   reporter.
 * Add support for CHROME_EXECUTABLE environment variable. This overrides any
   config file settings.
+* Support running tests by absolute file uri.
 
 ## 1.22.2
 
diff --git a/pkgs/test/README.md b/pkgs/test/README.md
index 14db941..4bc1c82 100644
--- a/pkgs/test/README.md
+++ b/pkgs/test/README.md
@@ -1,15 +1,20 @@
-[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/dart-lang/test/badge)](https://api.securityscorecards.dev/projects/github.com/dart-lang/test)
+[![pub package](https://img.shields.io/pub/v/test.svg)](https://pub.dev/packages/test)
+[![package publisher](https://img.shields.io/pub/publisher/test.svg)](https://pub.dev/packages/test/publisher)
 
 `test` provides a standard way of writing and running tests in Dart.
 
+## Using package:test
+
 * [Writing Tests](#writing-tests)
 * [Running Tests](#running-tests)
   * [Sharding Tests](#sharding-tests)
+  * [Test Concurrency](#test-concurrency)
   * [Shuffling Tests](#shuffling-tests)
   * [Selecting a Test Reporter](#selecting-a-test-reporter)
   * [Collecting Code Coverage](#collecting-code-coverage)
   * [Restricting Tests to Certain Platforms](#restricting-tests-to-certain-platforms)
   * [Platform Selectors](#platform-selectors)
+  * [Compiler Selectors](#compiler-selectors)
   * [Running Tests on Node.js](#running-tests-on-nodejs)
 * [Asynchronous Tests](#asynchronous-tests)
   * [Stream Matchers](#stream-matchers)
@@ -30,12 +35,12 @@
 
 ## Writing Tests
 
-Tests are specified using the top-level [`test()`] function, and test assertions
-are made using [`expect()`]:
+Tests are specified using the top-level [`test()`] function.
+Test asserts can be made using [`expect` from `package:matcher`][expect]
 
 [`test()`]: https://pub.dev/documentation/test_core/latest/test_core.scaffolding/test.html
 
-[`expect()`]: https://pub.dev/documentation/test_api/latest/expect/expect.html
+[expect]: https://pub.dev/documentation/matcher/latest/expect/expect.html
 
 ```dart
 import 'package:test/test.dart';
@@ -86,42 +91,6 @@
 }
 ```
 
-Any matchers from the [`matcher`] package can be used with `expect()` to do
-complex validations:
-
-[`matcher`]: https://pub.dev/documentation/matcher/latest/matcher/matcher-library.html
-
-```dart
-import 'package:test/test.dart';
-
-void main() {
-  test('.split() splits the string on the delimiter', () {
-    expect('foo,bar,baz', allOf([
-      contains('foo'),
-      isNot(startsWith('bar')),
-      endsWith('baz')
-    ]));
-  });
-}
-```
-
-You can also test exceptions with the [`throwsA()`] function or a matcher
-such as [`throwsFormatException`]:
-
-[`throwsA()`]: https://pub.dev/documentation/test_api/latest/expect/throwsA.html
-
-[`throwsFormatException`]: https://pub.dev/documentation/test_api/latest/expect/throwsFormatException-constant.html
-
-```dart
-import 'package:test/test.dart';
-
-void main() {
-  test('.parse() fails on invalid input', () {
-    expect(() => int.parse('X'), throwsFormatException);
-  });
-}
-```
-
 You can use the [`setUp()`] and [`tearDown()`] functions to share code between
 tests. The `setUp()` callback will run before every test in a group or test
 suite, and `tearDown()` will run after. `tearDown()` will run even if a test
@@ -167,9 +136,14 @@
 path/to/test.dart`, but this doesn't load the full test runner and will be
 missing some features.
 
-The test runner considers any file that ends with `_test.dart` to be a test
-file. If you don't pass any paths, it will run all the test files in your
-`test/` directory, making it easy to test your entire application at once.
+The test runner accepts one or more path arguments. If there are no path
+arguments the runner defaults to running tests under the `test/` directory. When
+running for `test/` or any other directory, the runner will recursively search
+the directory for files that match the test name pattern `*_test.dart`. The
+pattern can be overridden in `dart_test.yaml`. When a path argument is a file
+instead of a directory it will be run as a test, regardless of the file name.
+Arguments which use shell globbing should avoid including non-test files in the
+path argument.
 
 You can select specific tests cases to run by name using `dart test -n "test
 name"`. The string is interpreted as a regular expression, and only tests whose
@@ -184,6 +158,12 @@
 tests on both platforms with a single command: `dart test -p "chrome,vm"
 path/to/test.dart`.
 
+By default each platform has a default compiler, but some of them support
+more than one compiler. You can choose which compiler to use by passing
+`dart test -c source`, which would run all VM tests from source instead of
+compiling them to kernel. This also supports targeting a specific platform
+using normal platform selectors, like this `dart test -c vm:source`.
+
 ### Test Path Queries
 
 Some query parameters are supported on test paths, which allow you to filter the
@@ -223,6 +203,26 @@
 dart test --total-shards 3 --shard-index 1 path/to/test.dart
 dart test --total-shards 3 --shard-index 2 path/to/test.dart
 ```
+Sharding: This refers to the process of splitting up a large test suite into
+smaller subsets (called shards) that can be run independently. Sharding is
+particularly useful for distributed testing, where multiple machines are used
+to run tests simultaneously. By dividing the test suite into smaller subsets,
+you can run tests in parallel across multiple machines, which can significantly
+reduce the overall testing time.
+
+### Test concurrency
+
+Test suites run concurrently by default, using half of the host's CPU cores. Use
+`--concurrency` to control the number of test suites that runs concurrently,
+meaning that multiple tests in independent suites or platforms can run at the
+same time. For example, if you wanted to run the tests on 4 threads, you could
+run the tests as follows:
+
+```bash
+dart test --concurrency=4
+```
+This can speed up the overall testing process, especially if you have a large
+number of test suites.
 
 ### Shuffling Tests
 
@@ -381,6 +381,14 @@
 * `posix`: Whether the test is running on a POSIX operating system. This is
   equivalent to `!windows`.
 
+* `dart2js`: Whether the test has been compiled with Dart2Js.
+
+* `dart2wasm`: Whether the test has been compiled with Dart2Wasm.
+
+* `kernel`: Whether the test has been compiled to kernel.
+
+* `source`: Whether the test has been run with no compiler (from source).
+
 For example, if you wanted to run a test on every browser but Chrome, you would
 write `@TestOn('browser && !chrome')`.
 
@@ -439,189 +447,6 @@
 
 [early-handler]:https://dart.dev/guides/libraries/futures-error-handling#potential-problem-failing-to-register-error-handlers-early
 
-### Future Matchers
-
-There are a number of useful functions and matchers for more advanced
-asynchrony. The [`completion()`] matcher can be used to test `Futures`; it
-ensures that the test doesn't finish until the `Future` completes, and runs a
-matcher against that `Future`'s value.
-
-[`completion()`]: https://pub.dev/documentation/test_api/latest/expect/completion.html
-
-```dart
-import 'dart:async';
-
-import 'package:test/test.dart';
-
-void main() {
-  test('Future.value() returns the value', () {
-    expect(Future.value(10), completion(equals(10)));
-  });
-}
-```
-
-The [`throwsA()`] matcher and the various [`throwsExceptionType`] matchers work
-with both synchronous callbacks and asynchronous `Future`s. They ensure that a
-particular type of exception is thrown:
-
-[`throwsExceptionType`]: https://pub.dev/documentation/test_api/latest/expect/throwsException-constant.html
-
-```dart
-import 'dart:async';
-
-import 'package:test/test.dart';
-
-void main() {
-  test('Future.error() throws the error', () {
-    expect(Future.error('oh no'), throwsA(equals('oh no')));
-    expect(Future.error(StateError('bad state')), throwsStateError);
-  });
-}
-```
-
-The [`expectAsync()`] function wraps another function and has two jobs. First,
-it asserts that the wrapped function is called a certain number of times, and
-will cause the test to fail if it's called too often; second, it keeps the test
-from finishing until the function is called the requisite number of times.
-
-```dart
-import 'dart:async';
-
-import 'package:test/test.dart';
-
-void main() {
-  test('Stream.fromIterable() emits the values in the iterable', () {
-    var stream = Stream.fromIterable([1, 2, 3]);
-
-    stream.listen(expectAsync1((number) {
-      expect(number, inInclusiveRange(1, 3));
-    }, count: 3));
-  });
-}
-```
-
-[`expectAsync()`]: https://pub.dev/documentation/test_api/latest/test_api/expectAsync.html
-
-### Stream Matchers
-
-The `test` package provides a suite of powerful matchers for dealing with
-[asynchronous streams][Stream]. They're expressive and composable, and make it
-easy to write complex expectations about the values emitted by a stream. For
-example:
-
-[Stream]: https://api.dart.dev/stable/dart-async/Stream-class.html
-
-```dart
-import 'dart:async';
-
-import 'package:test/test.dart';
-
-void main() {
-  test('process emits status messages', () {
-    // Dummy data to mimic something that might be emitted by a process.
-    var stdoutLines = Stream.fromIterable([
-      'Ready.',
-      'Loading took 150ms.',
-      'Succeeded!'
-    ]);
-
-    expect(stdoutLines, emitsInOrder([
-      // Values match individual events.
-      'Ready.',
-
-      // Matchers also run against individual events.
-      startsWith('Loading took'),
-
-      // Stream matchers can be nested. This asserts that one of two events are
-      // emitted after the "Loading took" line.
-      emitsAnyOf(['Succeeded!', 'Failed!']),
-
-      // By default, more events are allowed after the matcher finishes
-      // matching. This asserts instead that the stream emits a done event and
-      // nothing else.
-      emitsDone
-    ]));
-  });
-}
-```
-
-A stream matcher can also match the [`async`] package's [`StreamQueue`] class,
-which allows events to be requested from a stream rather than pushed to the
-consumer. The matcher will consume the matched events, but leave the rest of the
-queue alone so that it can still be used by the test, unlike a normal `Stream`
-which can only have one subscriber. For example:
-
-[`async`]: https://pub.dev/packages/async
-
-[`StreamQueue`]: https://pub.dev/documentation/async/latest/async/StreamQueue-class.html
-
-```dart
-import 'dart:async';
-
-import 'package:async/async.dart';
-import 'package:test/test.dart';
-
-void main() {
-  test('process emits a WebSocket URL', () async {
-    // Wrap the Stream in a StreamQueue so that we can request events.
-    var stdout = StreamQueue(Stream.fromIterable([
-      'WebSocket URL:',
-      'ws://localhost:1234/',
-      'Waiting for connection...'
-    ]));
-
-    // Ignore lines from the process until it's about to emit the URL.
-    await expectLater(stdout, emitsThrough('WebSocket URL:'));
-
-    // Parse the next line as a URL.
-    var url = Uri.parse(await stdout.next);
-    expect(url.host, equals('localhost'));
-
-    // You can match against the same StreamQueue multiple times.
-    await expectLater(stdout, emits('Waiting for connection...'));
-  });
-}
-```
-
-The following built-in stream matchers are available:
-
-* [`emits()`] matches a single data event.
-* [`emitsError()`] matches a single error event.
-* [`emitsDone`] matches a single done event.
-* [`mayEmit()`] consumes events if they match an inner matcher, without
-  requiring them to match.
-* [`mayEmitMultiple()`] works like `mayEmit()`, but it matches events against
-  the matcher as many times as possible.
-* [`emitsAnyOf()`] consumes events matching one (or more) of several possible
-  matchers.
-* [`emitsInOrder()`] consumes events matching multiple matchers in a row.
-* [`emitsInAnyOrder()`] works like `emitsInOrder()`, but it allows the matchers
-  to match in any order.
-* [`neverEmits()`] matches a stream that finishes *without* matching an inner
-  matcher.
-
-You can also define your own custom stream matchers with [`StreamMatcher()`].
-
-[`emits()`]: https://pub.dev/documentation/test_api/latest/expect/emits.html
-
-[`emitsError()`]: https://pub.dev/documentation/test_api/latest/expect/emitsError.html
-
-[`emitsDone`]: https://pub.dev/documentation/test_api/latest/expect/emitsDone.html
-
-[`mayEmit()`]: https://pub.dev/documentation/test_api/latest/expect/mayEmit.html
-
-[`mayEmitMultiple()`]: https://pub.dev/documentation/test_api/latest/expect/mayEmitMultiple.html
-
-[`emitsAnyOf()`]: https://pub.dev/documentation/test_api/latest/expect/emitsAnyOf.html
-
-[`emitsInOrder()`]: https://pub.dev/documentation/test_api/latest/expect/emitsInOrder.html
-
-[`emitsInAnyOrder()`]: https://pub.dev/documentation/test_api/latest/expect/emitsInAnyOrder.html
-
-[`neverEmits()`]: https://pub.dev/documentation/test_api/latest/expect/neverEmits.html
-
-[`StreamMatcher()`]: https://pub.dev/documentation/test_api/latest/expect/StreamMatcher-class.html
-
 ## Running Tests With Custom HTML
 
 By default, the test runner will generate its own empty HTML file for browser
@@ -914,9 +739,9 @@
 Tests can be debugged interactively using platforms' built-in development tools.
 Tests running on browsers can use those browsers' development consoles to inspect
 the document, set breakpoints, and step through code. Those running on the Dart
-VM use [the Dart Observatory][observatory]'s .
+VM use [Dart DevTools][devtools].
 
-[observatory]: https://dart-lang.github.io/observatory/
+[devtools]: https://dart.dev/tools/dart-devtools
 
 The first step when debugging is to pass the `--pause-after-load` flag to the
 test runner. This pauses the browser after each test suite has loaded, so that
diff --git a/pkgs/test/dart_test.yaml b/pkgs/test/dart_test.yaml
index 68ba562..d51aebf 100644
--- a/pkgs/test/dart_test.yaml
+++ b/pkgs/test/dart_test.yaml
@@ -43,6 +43,9 @@
     add_tags: [dart2js]
     test_on: windows
     skip: https://github.com/dart-lang/test/issues/1614
+  edge:
+    add_tags: [dart2js]
+    test_on: windows
 
   # Tests that run pub. These tests may need to be excluded when there are local
   # dependency_overrides.
diff --git a/pkgs/test/doc/architecture.md b/pkgs/test/doc/architecture.md
index 7f9843a..110b51f 100644
--- a/pkgs/test/doc/architecture.md
+++ b/pkgs/test/doc/architecture.md
@@ -100,6 +100,7 @@
 by printing human-readable text. [`CompactReporter`][CompactReporter] is the
 default on Posix platforms, but others may be selected based on the
 `Configuration`. Nearly everything the user sees comes through the reporter.
+
 [Reporter]: https://github.com/dart-lang/test/tree/master/lib/src/runner/reporter.dart
 [CompactReporter]: https://github.com/dart-lang/test/tree/master/lib/src/runner/reporter/compact.dart
 
diff --git a/pkgs/test/doc/configuration.md b/pkgs/test/doc/configuration.md
index ee8f0a7..509ee1c 100644
--- a/pkgs/test/doc/configuration.md
+++ b/pkgs/test/doc/configuration.md
@@ -121,14 +121,14 @@
 
 ### `chain_stack_traces`
 
-This boolean field controls whether or not stack traces are chained. 
+This boolean field controls whether or not stack traces are chained.
 Disabling [`stack trace chaining`][stack trace chaining] will improve
-performance for heavily asynchronous code at the cost of debuggability. 
+performance for heavily asynchronous code at the cost of debuggability.
 
 [stack trace chaining]: https://github.com/dart-lang/stack_trace/blob/master/README.md#stack-chains
 
 ```yaml
-chain_stack_traces: false 
+chain_stack_traces: false
 ```
 
 ### `js_trace`
@@ -163,7 +163,7 @@
 
 ### `retry`
 
-This int field controls how many times a test is retried upon failure. 
+This int field controls how many times a test is retried upon failure.
 
 ```yaml
 tags:
@@ -417,6 +417,19 @@
 - firefox
 ```
 
+### `compilers`
+
+This field indicates which compilers tests should be compiled with by default.
+It allows the same compiler selectors that can be passed to `--compiler`. If
+a given platform has no supported compiler configured, it will use its default.
+
+```yaml
+compilers: [source]
+
+compilers:
+- source
+```
+
 ### `concurrency`
 
 This field indicates the default number of test suites to run in parallel. More
@@ -511,8 +524,8 @@
 ```yaml
 fold_stack_frames:
   except:
-  - test 
-  - stream_channel 
+  - test
+  - stream_channel
 ```
 
 Sample stack trace, note the absence of `package:test`
diff --git a/pkgs/test/lib/dart.js b/pkgs/test/lib/dart.js
index 9b49485..4a090ef 100644
--- a/pkgs/test/lib/dart.js
+++ b/pkgs/test/lib/dart.js
@@ -12,6 +12,7 @@
 // This mimics a MultiChannel-formatted message.
 var sendLoadException = function(message) {
   window.parent.postMessage({
+    // TODO: https://github.com/dart-lang/test/issues/2065 -  remove href
     "href": window.location.href,
     "data": [0, {"type": "loadException", "message": message}],
     "exception": true,
@@ -65,7 +66,14 @@
   var message = "Failed to load script at " + script.src +
       (event.message ? ": " + event.message : ".");
   sendLoadException(message);
-}
+};
+
+Array.from(document.querySelectorAll('script')).some(currentScript => {
+  if (currentScript.nonce) {
+    script.nonce = currentScript.nonce;
+    return true;
+  }
+});
 
 var parent = link.parentNode;
 document.currentScript = script;
diff --git a/pkgs/test/lib/expect.dart b/pkgs/test/lib/expect.dart
index 28f64f7..5e62622 100644
--- a/pkgs/test/lib/expect.dart
+++ b/pkgs/test/lib/expect.dart
@@ -2,4 +2,4 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-export 'package:test_api/expect.dart';
+export 'package:matcher/expect.dart';
diff --git a/pkgs/test/lib/src/executable.dart b/pkgs/test/lib/src/executable.dart
index 7daa8fd..6202c5a 100644
--- a/pkgs/test/lib/src/executable.dart
+++ b/pkgs/test/lib/src/executable.dart
@@ -12,16 +12,17 @@
 import 'runner/wasm/platform.dart';
 
 Future<void> main(List<String> args) async {
-  registerPlatformPlugin([Runtime.nodeJS], () => NodePlatform());
+  registerPlatformPlugin([Runtime.nodeJS], NodePlatform.new);
   registerPlatformPlugin([
     Runtime.chrome,
+    Runtime.edge,
     Runtime.firefox,
     Runtime.safari,
     Runtime.internetExplorer
-  ], () => BrowserPlatform.start());
+  ], BrowserPlatform.start);
   registerPlatformPlugin([
     Runtime.experimentalChromeWasm,
-  ], () => BrowserWasmPlatform.start());
+  ], BrowserWasmPlatform.start);
 
   await executable.main(args);
 }
diff --git a/pkgs/test/lib/src/runner/browser/browser.dart b/pkgs/test/lib/src/runner/browser/browser.dart
index 12f7fb8..be6d747 100644
--- a/pkgs/test/lib/src/runner/browser/browser.dart
+++ b/pkgs/test/lib/src/runner/browser/browser.dart
@@ -8,7 +8,6 @@
 
 import 'package:test_core/src/runner/application_exception.dart'; // ignore: implementation_imports
 import 'package:test_core/src/util/errors.dart'; // ignore: implementation_imports
-import 'package:typed_data/typed_data.dart';
 
 /// An interface for running browser instances.
 ///
@@ -21,12 +20,6 @@
 abstract class Browser {
   String get name;
 
-  /// The Observatory URL for this browser.
-  ///
-  /// This will complete to `null` for browsers that aren't running the Dart VM,
-  /// or if the Observatory URL can't be found.
-  Future<Uri?> get observatoryUrl async => null;
-
   /// The remote debugger URL for this browser.
   ///
   /// This will  complete to `null` for browsers that don't support remote
@@ -50,9 +43,9 @@
   final _onExitCompleter = Completer<void>();
 
   /// Standard IO streams for the underlying browser process.
-  final _ioSubscriptions = <StreamSubscription<List<int>>>[];
+  final _ioSubscriptions = <StreamSubscription<String>>[];
 
-  final output = Uint8Buffer();
+  final output = <String>[];
 
   /// Creates a new browser.
   ///
@@ -70,8 +63,10 @@
 
       void drainOutput(Stream<List<int>> stream) {
         try {
-          _ioSubscriptions
-              .add(stream.listen(output.addAll, cancelOnError: true));
+          _ioSubscriptions.add(stream
+              .transform(utf8.decoder)
+              .transform(const LineSplitter())
+              .listen(output.add, cancelOnError: true));
         } on StateError catch (_) {}
       }
 
@@ -96,7 +91,7 @@
       }
 
       if (!_closed && exitCode != 0) {
-        var outputString = utf8.decode(output);
+        var outputString = output.join('\n');
         var message = '$name failed with exit code $exitCode.';
         if (outputString.isNotEmpty) {
           message += '\nStandard output:\n$outputString';
diff --git a/pkgs/test/lib/src/runner/browser/browser_manager.dart b/pkgs/test/lib/src/runner/browser/browser_manager.dart
index b5d2abb..c38e103 100644
--- a/pkgs/test/lib/src/runner/browser/browser_manager.dart
+++ b/pkgs/test/lib/src/runner/browser/browser_manager.dart
@@ -8,11 +8,11 @@
 import 'package:async/async.dart';
 import 'package:pool/pool.dart';
 import 'package:stream_channel/stream_channel.dart';
-// ignore: deprecated_member_use
-import 'package:test_api/backend.dart' show Runtime, StackTraceMapper;
+import 'package:test_api/backend.dart' show Compiler, Runtime, StackTraceMapper;
 import 'package:test_core/src/runner/application_exception.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/environment.dart'; // ignore: implementation_imports
+import 'package:test_core/src/runner/load_exception.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/plugin/platform_helpers.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/runner_suite.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/suite.dart'; // ignore: implementation_imports
@@ -24,6 +24,7 @@
 import 'chrome.dart';
 import 'firefox.dart';
 import 'internet_explorer.dart';
+import 'microsoft_edge.dart';
 import 'safari.dart';
 
 /// A class that manages the connection to a single running browser.
@@ -142,7 +143,7 @@
       if (attempt >= _maxRetries) {
         throw ApplicationException(
             'Timed out waiting for ${runtime.name} to connect.\n'
-            'Browser output: ${utf8.decode(browser.output)}');
+            'Browser output: ${browser.output.join('\n')}');
       }
       return _start(runtime, url, future, settings, configuration, ++attempt);
     });
@@ -152,21 +153,17 @@
   ///
   /// If [debug] is true, starts the browser in debug mode.
   static Browser _newBrowser(Uri url, Runtime browser,
-      ExecutableSettings settings, Configuration configuration) {
-    switch (browser.root) {
-      case Runtime.chrome:
-      case Runtime.experimentalChromeWasm:
-        return Chrome(url, configuration, settings: settings);
-      case Runtime.firefox:
-        return Firefox(url, settings: settings);
-      case Runtime.safari:
-        return Safari(url, settings: settings);
-      case Runtime.internetExplorer:
-        return InternetExplorer(url, settings: settings);
-      default:
-        throw ArgumentError('$browser is not a browser.');
-    }
-  }
+          ExecutableSettings settings, Configuration configuration) =>
+      switch (browser.root) {
+        Runtime.chrome ||
+        Runtime.experimentalChromeWasm =>
+          Chrome(url, configuration, settings: settings),
+        Runtime.firefox => Firefox(url, settings: settings),
+        Runtime.safari => Safari(url, settings: settings),
+        Runtime.internetExplorer => InternetExplorer(url, settings: settings),
+        Runtime.edge => MicrosoftEdge(url, configuration, settings: settings),
+        _ => throw ArgumentError('$browser is not a browser.'),
+      };
 
   /// Creates a new BrowserManager that communicates with [browser] over
   /// [webSocket].
@@ -205,10 +202,9 @@
   }
 
   /// Loads [_BrowserEnvironment].
-  Future<_BrowserEnvironment> _loadBrowserEnvironment() async {
-    return _BrowserEnvironment(this, await _browser.observatoryUrl,
-        await _browser.remoteDebuggerUrl, _onRestartController.stream);
-  }
+  Future<_BrowserEnvironment> _loadBrowserEnvironment() async =>
+      _BrowserEnvironment(
+          this, await _browser.remoteDebuggerUrl, _onRestartController.stream);
 
   /// Tells the browser the load a test suite from the URL [url].
   ///
@@ -219,12 +215,13 @@
   /// If [mapper] is passed, it's used to map stack traces for errors coming
   /// from this test suite.
   Future<RunnerSuite> load(String path, Uri url, SuiteConfiguration suiteConfig,
-      Map<String, Object?> message,
-      {StackTraceMapper? mapper}) async {
+      Map<String, Object?> message, Compiler compiler,
+      {StackTraceMapper? mapper, Duration? timeout}) async {
     url = url.replace(
         fragment: Uri.encodeFull(jsonEncode({
       'metadata': suiteConfig.metadata.serialize(),
-      'browser': _runtime.identifier
+      'browser': _runtime.identifier,
+      'compiler': compiler.serialize(),
     })));
 
     var suiteID = _suiteID++;
@@ -245,7 +242,7 @@
       sink.close();
     }));
 
-    return await _pool.withResource<RunnerSuite>(() async {
+    var suite = _pool.withResource<RunnerSuite>(() async {
       _channel.sink.add({
         'command': 'loadSuite',
         'url': url.toString(),
@@ -256,7 +253,7 @@
       try {
         controller = deserializeSuite(
             path,
-            currentPlatform(_runtime),
+            currentPlatform(_runtime, compiler),
             suiteConfig,
             await _environment,
             suiteChannel.cast(),
@@ -278,6 +275,15 @@
         rethrow;
       }
     });
+    if (timeout != null) {
+      suite = suite.timeout(timeout, onTimeout: () {
+        throw LoadException(
+            path,
+            'Timed out waiting for browser to load test suite. '
+            'Browser output: ${_browser.output.join('\n')}');
+      });
+    }
+    return suite;
   }
 
   /// An implementation of [Environment.displayPause].
@@ -342,7 +348,7 @@
   final supportsDebugging = true;
 
   @override
-  final Uri? observatoryUrl;
+  Null get observatoryUrl => null;
 
   @override
   final Uri? remoteDebuggerUrl;
@@ -350,8 +356,7 @@
   @override
   final Stream<void> onRestart;
 
-  _BrowserEnvironment(this._manager, this.observatoryUrl,
-      this.remoteDebuggerUrl, this.onRestart);
+  _BrowserEnvironment(this._manager, this.remoteDebuggerUrl, this.onRestart);
 
   @override
   CancelableOperation<void> displayPause() => _manager._displayPause();
diff --git a/pkgs/test/lib/src/runner/browser/chrome.dart b/pkgs/test/lib/src/runner/browser/chrome.dart
index 0feb397..a67b8ee 100644
--- a/pkgs/test/lib/src/runner/browser/chrome.dart
+++ b/pkgs/test/lib/src/runner/browser/chrome.dart
@@ -16,6 +16,7 @@
 
 import '../executable_settings.dart';
 import 'browser.dart';
+import 'chromium.dart';
 import 'default_settings.dart';
 
 /// A class for running an instance of Chrome.
@@ -45,39 +46,20 @@
     var idToUrl = <String, String>{};
     return Chrome._(() async {
       Future<Process> tryPort([int? port]) async {
-        var dir = createTempDir();
-        var args = [
-          '--user-data-dir=$dir',
-          url.toString(),
-          '--enable-logging=stdout',
-          '--v=1',
-          '--disable-extensions',
-          '--disable-popup-blocking',
-          '--bwsi',
-          '--no-first-run',
-          '--no-default-browser-check',
-          '--disable-default-apps',
-          '--disable-translate',
-          '--disable-dev-shm-usage',
-          if (settings!.headless && !configuration.pauseAfterLoad) ...[
-            '--headless',
-            '--disable-gpu',
+        var process = await ChromiumBasedBrowser.chrome.spawn(
+          url,
+          configuration,
+          settings: settings,
+          additionalArgs: [
+            if (port != null)
+              // Chrome doesn't provide any way of ensuring that this port was
+              // successfully bound. It produces an error if the binding fails,
+              // but without a reliable and fast way to tell if it succeeded
+              // that doesn't provide us much. It's very unlikely that this port
+              // will fail, though.
+              '--remote-debugging-port=$port',
           ],
-          if (!configuration.debug)
-            // We don't actually connect to the remote debugger, but Chrome will
-            // close as soon as the page is loaded if we don't turn it on.
-            '--remote-debugging-port=0',
-          ...settings.arguments,
-          if (port != null)
-            // Chrome doesn't provide any way of ensuring that this port was
-            // successfully bound. It produces an error if the binding fails,
-            // but without a reliable and fast way to tell if it succeeded that
-            // doesn't provide us much. It's very unlikely that this port will
-            // fail, though.
-            '--remote-debugging-port=$port',
-        ];
-
-        var process = await Process.start(settings.executable, args);
+        );
 
         if (port != null) {
           remoteDebuggerCompleter.complete(
@@ -88,9 +70,6 @@
           remoteDebuggerCompleter.complete(null);
         }
 
-        unawaited(process.exitCode
-            .then((_) => Directory(dir).deleteSync(recursive: true)));
-
         return process;
       }
 
diff --git a/pkgs/test/lib/src/runner/browser/chromium.dart b/pkgs/test/lib/src/runner/browser/chromium.dart
new file mode 100644
index 0000000..e2a456f
--- /dev/null
+++ b/pkgs/test/lib/src/runner/browser/chromium.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. 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:io';
+
+import 'package:test/src/runner/browser/default_settings.dart';
+import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
+import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports
+import 'package:test_core/src/util/io.dart'; // ignore: implementation_imports
+
+import '../executable_settings.dart';
+
+enum ChromiumBasedBrowser {
+  chrome(Runtime.chrome),
+  microsoftEdge(Runtime.edge);
+
+  final Runtime runtime;
+
+  const ChromiumBasedBrowser(this.runtime);
+
+  Future<Process> spawn(
+    Uri url,
+    Configuration configuration, {
+    ExecutableSettings? settings,
+    List<String> additionalArgs = const [],
+  }) async {
+    settings ??= defaultSettings[runtime];
+
+    var dir = createTempDir();
+    var args = [
+      '--user-data-dir=$dir',
+      url.toString(),
+      '--enable-logging=stderr',
+      '--v=0',
+      '--disable-extensions',
+      '--disable-popup-blocking',
+      '--bwsi',
+      '--no-first-run',
+      '--no-default-browser-check',
+      '--disable-default-apps',
+      '--disable-translate',
+      '--disable-dev-shm-usage',
+      if (settings!.headless && !configuration.pauseAfterLoad) ...[
+        '--headless',
+        '--disable-gpu',
+      ],
+      if (!configuration.debug)
+        // We don't actually connect to the remote debugger, but Chrome will
+        // close as soon as the page is loaded if we don't turn it on.
+        '--remote-debugging-port=0',
+      ...settings.arguments,
+      ...additionalArgs,
+    ];
+
+    var process = await Process.start(settings.executable, args);
+
+    unawaited(process.exitCode.then((_) => Directory(dir).deleteWithRetry()));
+
+    return process;
+  }
+}
diff --git a/pkgs/test/lib/src/runner/browser/default_settings.dart b/pkgs/test/lib/src/runner/browser/default_settings.dart
index d608804..929d777 100644
--- a/pkgs/test/lib/src/runner/browser/default_settings.dart
+++ b/pkgs/test/lib/src/runner/browser/default_settings.dart
@@ -13,13 +13,23 @@
       linuxExecutable: 'google-chrome',
       macOSExecutable:
           '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
-      windowsExecutable: r'Google\Chrome\Application\chrome.exe'),
+      windowsExecutable: r'Google\Chrome\Application\chrome.exe',
+      environmentOverride: 'CHROME_EXECUTABLE'),
+  Runtime.edge: ExecutableSettings(
+    linuxExecutable: 'microsoft-edge-stable',
+    windowsExecutable: r'Microsoft\Edge\Application\msedge.exe',
+    macOSExecutable:
+        '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
+    environmentOverride: 'MS_EDGE_EXECUTABLE',
+  ),
   Runtime.firefox: ExecutableSettings(
       linuxExecutable: 'firefox',
       macOSExecutable: '/Applications/Firefox.app/Contents/MacOS/firefox-bin',
-      windowsExecutable: r'Mozilla Firefox\firefox.exe'),
+      windowsExecutable: r'Mozilla Firefox\firefox.exe',
+      environmentOverride: 'FIREFOX_EXECUTABLE'),
   Runtime.internetExplorer:
       ExecutableSettings(windowsExecutable: r'Internet Explorer\iexplore.exe'),
   Runtime.safari: ExecutableSettings(
-      macOSExecutable: '/Applications/Safari.app/Contents/MacOS/Safari')
+      macOSExecutable: '/Applications/Safari.app/Contents/MacOS/Safari',
+      environmentOverride: 'SAFARI_EXECUTABLE'),
 });
diff --git a/pkgs/test/lib/src/runner/browser/dom.dart b/pkgs/test/lib/src/runner/browser/dom.dart
index 98ed0e9..2783e92 100644
--- a/pkgs/test/lib/src/runner/browser/dom.dart
+++ b/pkgs/test/lib/src/runner/browser/dom.dart
@@ -11,6 +11,8 @@
 class Window extends EventTarget {}
 
 extension WindowExtension on Window {
+  @pragma('dart2js:as:trust')
+  Window get parent => js_util.getProperty<dynamic>(this, 'parent') as Window;
   external Location get location;
   CSSStyleDeclaration? getComputedStyle(Element elt, [String? pseudoElt]) =>
       js_util.callMethod(this, 'getComputedStyle', <Object>[
@@ -85,7 +87,7 @@
   external Node appendChild(Node node);
   void remove() {
     if (parentNode != null) {
-      final Node parent = parentNode!;
+      final parent = parentNode!;
       parent.removeChild(this);
     }
   }
@@ -135,10 +137,22 @@
   external String get origin;
   List<MessagePort> get ports =>
       js_util.getProperty<List>(this, 'ports').cast<MessagePort>();
+
+  /// The source may be a `WindowProxy`, a `MessagePort`, or a `ServiceWorker`.
+  ///
+  /// When a message is sent from an iframe through `window.parent.postMessage`
+  /// the source will be a `WindowProxy` which has the same methods as [Window].
+  @pragma('dart2js:as:trust')
+  MessageEventSource get source =>
+      js_util.getProperty<dynamic>(this, 'source') as MessageEventSource;
 }
 
 @JS()
 @staticInterop
+class MessageEventSource {}
+
+@JS()
+@staticInterop
 class Location {}
 
 extension LocationExtension on Location {
@@ -221,7 +235,7 @@
     js_util.getProperty(window, constructorName);
 
 Object? _callConstructor(String constructorName, List<Object?> args) {
-  final Object? constructor = _findConstructor(constructorName);
+  final constructor = _findConstructor(constructorName);
   if (constructor == null) {
     return null;
   }
diff --git a/pkgs/test/lib/src/runner/browser/firefox.dart b/pkgs/test/lib/src/runner/browser/firefox.dart
index 5b68018..39e1ac5 100644
--- a/pkgs/test/lib/src/runner/browser/firefox.dart
+++ b/pkgs/test/lib/src/runner/browser/firefox.dart
@@ -47,11 +47,11 @@
       '--no-remote',
       ...settings.arguments,
     ], environment: {
-      'MOZ_CRASHREPORTER_DISABLE': '1'
+      'MOZ_CRASHREPORTER_DISABLE': '1',
+      'MOZ_AUTOMATION': '1',
     });
 
-    unawaited(process.exitCode
-        .then((_) => Directory(dir).deleteSync(recursive: true)));
+    unawaited(process.exitCode.then((_) => Directory(dir).deleteWithRetry()));
 
     return process;
   }
diff --git a/pkgs/test/lib/src/runner/browser/microsoft_edge.dart b/pkgs/test/lib/src/runner/browser/microsoft_edge.dart
new file mode 100644
index 0000000..08fa8e2
--- /dev/null
+++ b/pkgs/test/lib/src/runner/browser/microsoft_edge.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports
+
+import '../executable_settings.dart';
+import 'browser.dart';
+import 'chromium.dart';
+
+/// A class for running an instance of Microsoft Edge, a Chromium-based browser.
+class MicrosoftEdge extends Browser {
+  @override
+  String get name => 'Edge';
+
+  MicrosoftEdge(Uri url, Configuration configuration,
+      {ExecutableSettings? settings})
+      : super(() => ChromiumBasedBrowser.microsoftEdge.spawn(
+              url,
+              configuration,
+              settings: settings,
+            ));
+}
diff --git a/pkgs/test/lib/src/runner/browser/platform.dart b/pkgs/test/lib/src/runner/browser/platform.dart
index 089a175..55ff255 100644
--- a/pkgs/test/lib/src/runner/browser/platform.dart
+++ b/pkgs/test/lib/src/runner/browser/platform.dart
@@ -15,9 +15,8 @@
 import 'package:shelf_packages_handler/shelf_packages_handler.dart';
 import 'package:shelf_static/shelf_static.dart';
 import 'package:shelf_web_socket/shelf_web_socket.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/backend.dart'
-    show Runtime, StackTraceMapper, SuitePlatform;
+    show Compiler, Runtime, StackTraceMapper, SuitePlatform;
 import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/dart2js_compiler_pool.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/load_exception.dart'; // ignore: implementation_imports
@@ -215,6 +214,14 @@
       throw ArgumentError('$browser is not a browser.');
     }
 
+    var compiler = platform.compiler;
+    // Technically, ddc is supported through --precompiled. But we don't expect
+    // any specific compiler setting in that case.
+    if (compiler != Compiler.dart2js) {
+      throw StateError('Unsupported compiler for $browser platform '
+          '$compiler');
+    }
+
     var htmlPathFromTestPath = '${p.withoutExtension(path)}.html';
     if (File(htmlPathFromTestPath).existsSync()) {
       if (_config.customHtmlTemplatePath != null &&
@@ -271,8 +278,14 @@
     var browserManager = await _browserManagerFor(browser);
     if (_closed || browserManager == null) return null;
 
-    var suite = await browserManager.load(path, suiteUrl, suiteConfig, message,
-        mapper: _mappers[path]);
+    var timeout = const Duration(seconds: 30);
+    if (suiteConfig.metadata.timeout.apply(timeout) case final suiteTimeout?
+        when suiteTimeout > timeout) {
+      timeout = suiteTimeout;
+    }
+    var suite = await browserManager.load(
+        path, suiteUrl, suiteConfig, message, platform.compiler,
+        mapper: _mappers[path], timeout: timeout);
     if (_closed) return null;
     return suite;
   }
@@ -463,7 +476,7 @@
         ]);
 
         if (_config.pubServeUrl == null) {
-          Directory(_compiledDir!).deleteSync(recursive: true);
+          await Directory(_compiledDir!).deleteWithRetry();
         } else {
           _http!.close();
         }
diff --git a/pkgs/test/lib/src/runner/browser/post_message_channel.dart b/pkgs/test/lib/src/runner/browser/post_message_channel.dart
index fbb6cfc..fa71d3d 100644
--- a/pkgs/test/lib/src/runner/browser/post_message_channel.dart
+++ b/pkgs/test/lib/src/runner/browser/post_message_channel.dart
@@ -2,60 +2,29 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library test.src.runner.browser.post_message_channel;
-
 import 'dart:js_util';
 
-import 'package:js/js.dart';
 import 'package:stream_channel/stream_channel.dart';
 
 import 'dom.dart' as dom;
 
-// Avoid using this from dart:html to work around dart-lang/sdk#32113.
-@JS('window.parent.postMessage')
-external void _postParentMessage(Object message, String targetOrigin);
-
-/// Constructs a [StreamChannel] wrapping [MessageChannel] communication with
-/// the host page.
+/// Constructs a [StreamChannel] wrapping a new [MessageChannel] communicating
+/// with the host page.
+///
+/// Sends a [MessagePort] to the host page for the channel.
 StreamChannel<Object?> postMessageChannel() {
   var controller = StreamChannelController<Object?>(sync: true);
-
-  // Listen for a message from the host that transfers a message port, then
-  // cancel the subscription.  This is important to prevent multiple
-  // subscriptions if the test is ever hot restarted.
-  late final dom.Subscription subscription;
-  subscription =
-      dom.Subscription(dom.window, 'message', allowInterop((dom.Event event) {
-    // A message on the Window can theoretically come from any website. It's
-    // very unlikely that a malicious site would care about hacking someone's
-    // unit tests, let alone be able to find the test server while it's
-    // running, but it's good practice to check the origin anyway.
-    final message = event as dom.MessageEvent;
-    if (message.origin == dom.window.location.origin &&
-        message.data == 'port') {
-      subscription.cancel();
-      var port = message.ports.first;
-      port.start();
-      var portSubscription =
-          dom.Subscription(port, 'message', allowInterop((dom.Event event) {
-        controller.local.sink.add((event as dom.MessageEvent).data);
-      }));
-
-      controller.local.stream.listen((data) {
-        port.postMessage({'data': data});
-      }, onDone: () {
-        port.postMessage({'event': 'done'});
-        portSubscription.cancel();
-      });
-    }
+  var channel = dom.createMessageChannel();
+  dom.window.parent
+      .postMessage('port', dom.window.location.origin, [channel.port2]);
+  var portSubscription = dom.Subscription(channel.port1, 'message',
+      allowInterop((dom.Event event) {
+    controller.local.sink.add((event as dom.MessageEvent).data);
   }));
+  channel.port1.start();
 
-  // Send a ready message once we're listening so the host knows it's safe to
-  // start sending events.
-  // TODO(nweiz): Stop manually adding href here once issue 22554 is fixed.
-  _postParentMessage(
-      jsify({'href': dom.window.location.href, 'ready': true}) as Object,
-      dom.window.location.origin);
+  controller.local.stream
+      .listen(channel.port1.postMessage, onDone: portSubscription.cancel);
 
   return controller.foreign;
 }
diff --git a/pkgs/test/lib/src/runner/browser/safari.dart b/pkgs/test/lib/src/runner/browser/safari.dart
index 41cd896..6689a8b 100644
--- a/pkgs/test/lib/src/runner/browser/safari.dart
+++ b/pkgs/test/lib/src/runner/browser/safari.dart
@@ -40,8 +40,7 @@
     var process = await Process.start(
         settings.executable, settings.arguments.toList()..add(redirect));
 
-    unawaited(process.exitCode
-        .then((_) => Directory(dir).deleteSync(recursive: true)));
+    unawaited(process.exitCode.then((_) => Directory(dir).deleteWithRetry()));
 
     return process;
   }
diff --git a/pkgs/test/lib/src/runner/browser/static/host.dart.js b/pkgs/test/lib/src/runner/browser/static/host.dart.js
index 86173e4..ff080c0 100644
--- a/pkgs/test/lib/src/runner/browser/static/host.dart.js
+++ b/pkgs/test/lib/src/runner/browser/static/host.dart.js
@@ -1,4 +1,4 @@
-// Generated by dart2js (NullSafetyMode.sound, csp, deferred-serialization, intern-composite-values), the Dart to JavaScript compiler version: 2.19.0-edge.e4643b54dfba2a4362e47874e742cdffa2892171.
+// Generated by dart2js (NullSafetyMode.sound, csp, deferred-serialization, intern-composite-values), the Dart to JavaScript compiler version: 3.2.0-36.0.dev.
 // The code supports the following hooks:
 // dartPrint(message):
 //    if this function is defined it is called instead of the Dart [print]
@@ -9,12 +9,14 @@
 //    directly. Instead, a closure that will invoke [main], and its arguments
 //    [args] is passed to [dartMainRunner].
 //
-// dartDeferredLibraryLoader(uri, successCallback, errorCallback, loadId):
+// dartDeferredLibraryLoader(uri, successCallback, errorCallback, loadId, loadPriority):
 //    if this function is defined, it will be called when a deferred library
 //    is loaded. It should load and eval the javascript of `uri`, and call
 //    successCallback. If it fails to do so, it should call errorCallback with
 //    an error. The loadId argument is the deferred import that resulted in
-//    this uri being loaded.
+//    this uri being loaded. The loadPriority argument is the priority the
+//    library should be loaded with as specified in the code via the
+//    load-priority annotation (0: normal, 1: high).
 //
 // dartCallInstrumentation(id, qualifiedName):
 //    if this function is defined, it will be called at each entry of a
@@ -44,7 +46,7 @@
     };
     cls.prototype = {p: {}};
     var object = new cls();
-    if (!(object.__proto__ && object.__proto__.p === cls.prototype.p))
+    if (!(Object.getPrototypeOf(object) && Object.getPrototypeOf(object).p === cls.prototype.p))
       return false;
     try {
       if (typeof navigator != "undefined" && typeof navigator.userAgent == "string" && navigator.userAgent.indexOf("Chrome/") >= 0)
@@ -63,7 +65,7 @@
     cls.prototype["$is" + cls.name] = cls;
     if (sup != null) {
       if (supportsDirectProtoAccess) {
-        cls.prototype.__proto__ = sup.prototype;
+        Object.setPrototypeOf(cls.prototype, sup.prototype);
         return;
       }
       var clsPrototype = Object.create(sup.prototype);
@@ -236,14 +238,10 @@
   }
   var A = {JS_CONST: function JS_CONST() {
     },
-    LateError$fieldADI(fieldName) {
-      return new A.LateError("Field '" + fieldName + "' has been assigned during initialization.");
-    },
-    LateError$fieldNI(fieldName) {
-      return new A.LateError("Field '" + fieldName + "' has not been initialized.");
-    },
-    LateError$fieldAI(fieldName) {
-      return new A.LateError("Field '" + fieldName + "' has already been initialized.");
+    CastIterable_CastIterable(source, $S, $T) {
+      if ($S._eval$1("EfficientLengthIterable<0>")._is(source))
+        return new A._EfficientLengthCastIterable(source, $S._eval$1("@<0>")._bind$1($T)._eval$1("_EfficientLengthCastIterable<1,2>"));
+      return new A.CastIterable(source, $S._eval$1("@<0>")._bind$1($T)._eval$1("CastIterable<1,2>"));
     },
     hexDigitValue(char) {
       var letter,
@@ -268,6 +266,13 @@
     checkNotNullable(value, $name, $T) {
       return value;
     },
+    isToStringVisiting(object) {
+      var t1, i;
+      for (t1 = $.toStringVisiting.length, i = 0; i < t1; ++i)
+        if (object === $.toStringVisiting[i])
+          return true;
+      return false;
+    },
     SubListIterable$(_iterable, _start, _endOrLength, $E) {
       A.RangeError_checkNotNegative(_start, "start");
       if (_endOrLength != null) {
@@ -290,6 +295,17 @@
         return new A.EfficientLengthTakeIterable(iterable, takeCount, $E._eval$1("EfficientLengthTakeIterable<0>"));
       return new A.TakeIterable(iterable, takeCount, $E._eval$1("TakeIterable<0>"));
     },
+    SkipIterable_SkipIterable(iterable, count, $E) {
+      var _s5_ = "count";
+      if (type$.EfficientLengthIterable_dynamic._is(iterable)) {
+        A.ArgumentError_checkNotNull(count, _s5_, type$.int);
+        A.RangeError_checkNotNegative(count, _s5_);
+        return new A.EfficientLengthSkipIterable(iterable, count, $E._eval$1("EfficientLengthSkipIterable<0>"));
+      }
+      A.ArgumentError_checkNotNull(count, _s5_, type$.int);
+      A.RangeError_checkNotNegative(count, _s5_);
+      return new A.SkipIterable(iterable, count, $E._eval$1("SkipIterable<0>"));
+    },
     IterableElementError_noElement() {
       return new A.StateError("No element");
     },
@@ -307,6 +323,26 @@
       _._handleError = _._handleData = null;
       _.$ti = t2;
     },
+    _CastIterableBase: function _CastIterableBase() {
+    },
+    CastIterator: function CastIterator(t0, t1) {
+      this._source = t0;
+      this.$ti = t1;
+    },
+    CastIterable: function CastIterable(t0, t1) {
+      this._source = t0;
+      this.$ti = t1;
+    },
+    _EfficientLengthCastIterable: function _EfficientLengthCastIterable(t0, t1) {
+      this._source = t0;
+      this.$ti = t1;
+    },
+    _CastListBase: function _CastListBase() {
+    },
+    CastList: function CastList(t0, t1) {
+      this._source = t0;
+      this.$ti = t1;
+    },
     LateError: function LateError(t0) {
       this._message = t0;
     },
@@ -324,7 +360,7 @@
     SubListIterable: function SubListIterable(t0, t1, t2, t3) {
       var _ = this;
       _.__internal$_iterable = t0;
-      _.__internal$_start = t1;
+      _._start = t1;
       _._endOrLength = t2;
       _.$ti = t3;
     },
@@ -396,6 +432,21 @@
       this._remaining = t1;
       this.$ti = t2;
     },
+    SkipIterable: function SkipIterable(t0, t1, t2) {
+      this.__internal$_iterable = t0;
+      this._skipCount = t1;
+      this.$ti = t2;
+    },
+    EfficientLengthSkipIterable: function EfficientLengthSkipIterable(t0, t1, t2) {
+      this.__internal$_iterable = t0;
+      this._skipCount = t1;
+      this.$ti = t2;
+    },
+    SkipIterator: function SkipIterator(t0, t1, t2) {
+      this._iterator = t0;
+      this._skipCount = t1;
+      this.$ti = t2;
+    },
     SkipWhileIterable: function SkipWhileIterable(t0, t1, t2) {
       this.__internal$_iterable = t0;
       this._f = t1;
@@ -408,6 +459,9 @@
       _._hasSkipped = false;
       _.$ti = t2;
     },
+    EmptyIterable: function EmptyIterable(t0) {
+      this.$ti = t0;
+    },
     EmptyIterator: function EmptyIterator(t0) {
       this.$ti = t0;
     },
@@ -432,6 +486,8 @@
     Symbol: function Symbol(t0) {
       this._name = t0;
     },
+    __CastListBase__CastIterableBase_ListMixin: function __CastListBase__CastIterableBase_ListMixin() {
+    },
     ConstantMap__throwUnmodifiable() {
       throw A.wrapException(A.UnsupportedError$("Cannot modify unmodifiable Map"));
     },
@@ -501,7 +557,7 @@
         maxCharCode = radix <= 10 ? 47 + radix : 86 + radix;
         digitsPart = match[1];
         for (t1 = digitsPart.length, i = 0; i < t1; ++i)
-          if ((B.JSString_methods._codeUnitAt$1(digitsPart, i) | 32) > maxCharCode)
+          if ((digitsPart.charCodeAt(i) | 32) > maxCharCode)
             return _null;
       }
       return parseInt(source, radix);
@@ -527,6 +583,15 @@
       }
       return A._rtiToString(A.instanceType(object), null);
     },
+    Primitives_safeToString(object) {
+      if (typeof object == "number" || A._isBool(object))
+        return J.toString$0$(object);
+      if (typeof object == "string")
+        return JSON.stringify(object);
+      if (object instanceof A.Closure)
+        return object.toString$0(0);
+      return "Instance of '" + A.Primitives_objectTypeName(object) + "'";
+    },
     Primitives_currentUri() {
       if (!!self.location)
         return self.location.href;
@@ -599,7 +664,7 @@
     },
     Primitives_lazyAsJsDate(receiver) {
       if (receiver.date === void 0)
-        receiver.date = new Date(receiver._value);
+        receiver.date = new Date(receiver._core$_value);
       return receiver.date;
     },
     Primitives_getYear(receiver) {
@@ -754,7 +819,7 @@
         return new A.ArgumentError(true, index, _s5_, null);
       $length = A._asInt(J.get$length$asx(indexable));
       if (index < 0 || index >= $length)
-        return A.IndexError$(index, indexable, _s5_, null, $length);
+        return A.IndexError$withLength(index, $length, indexable, _s5_);
       return A.RangeError$value(index, _s5_);
     },
     diagnoseRangeError(start, end, $length) {
@@ -769,10 +834,12 @@
       return new A.ArgumentError(true, object, null, null);
     },
     wrapException(ex) {
-      var wrapper, t1;
+      return A.initializeExceptionWrapper(new Error(), ex);
+    },
+    initializeExceptionWrapper(wrapper, ex) {
+      var t1;
       if (ex == null)
-        ex = new A.NullThrownError();
-      wrapper = new Error();
+        ex = new A.TypeError();
       wrapper.dartException = ex;
       t1 = A.toStringWrapper;
       if ("defineProperty" in Object) {
@@ -788,6 +855,9 @@
     throwExpression(ex) {
       throw A.wrapException(ex);
     },
+    throwExpressionWithWrapper(ex, wrapper) {
+      throw A.initializeExceptionWrapper(wrapper, ex);
+    },
     throwConcurrentModificationError(collection) {
       throw A.wrapException(A.ConcurrentModificationError$(collection));
     },
@@ -829,13 +899,8 @@
       return new A.JsNoSuchMethodError(_message, t2, t1 ? null : match.receiver);
     },
     unwrapException(ex) {
-      var t1;
       if (ex == null)
         return new A.NullThrownFromJavaScriptException(ex);
-      if (ex instanceof A.ExceptionAndStackTrace) {
-        t1 = ex.dartException;
-        return A.saveStackTrace(ex, t1 == null ? type$.Object._as(t1) : t1);
-      }
       if (typeof ex !== "object")
         return ex;
       if ("dartException" in ex)
@@ -943,8 +1008,6 @@
     },
     getTraceFromException(exception) {
       var trace;
-      if (exception instanceof A.ExceptionAndStackTrace)
-        return exception.stackTrace;
       if (exception == null)
         return new A._StackTrace(exception);
       trace = exception.$cachedTrace;
@@ -953,10 +1016,11 @@
       return exception.$cachedTrace = new A._StackTrace(exception);
     },
     objectHashCode(object) {
-      if (object == null || typeof object != "object")
+      if (object == null)
         return J.get$hashCode$(object);
-      else
+      if (typeof object == "object")
         return A.Primitives_objectHashCode(object);
+      return J.get$hashCode$(object);
     },
     fillLiteralMap(keyValuePairs, result) {
       var index, index0, index1,
@@ -968,7 +1032,7 @@
       }
       return result;
     },
-    invokeClosure(closure, numberOfArguments, arg1, arg2, arg3, arg4) {
+    _invokeClosure(closure, numberOfArguments, arg1, arg2, arg3, arg4) {
       type$.Function._as(closure);
       switch (A._asInt(numberOfArguments)) {
         case 0:
@@ -985,19 +1049,41 @@
       throw A.wrapException(new A._Exception("Unsupported number of arguments for wrapped closure"));
     },
     convertDartClosureToJS(closure, arity) {
-      var $function;
-      if (closure == null)
-        return null;
-      $function = closure.$identity;
+      var $function = closure.$identity;
       if (!!$function)
         return $function;
-      $function = function(closure, arity, invoke) {
+      $function = A.convertDartClosureToJSUncached(closure, arity);
+      closure.$identity = $function;
+      return $function;
+    },
+    convertDartClosureToJSUncached(closure, arity) {
+      var entry;
+      switch (arity) {
+        case 0:
+          entry = closure.call$0;
+          break;
+        case 1:
+          entry = closure.call$1;
+          break;
+        case 2:
+          entry = closure.call$2;
+          break;
+        case 3:
+          entry = closure.call$3;
+          break;
+        case 4:
+          entry = closure.call$4;
+          break;
+        default:
+          entry = null;
+      }
+      if (entry != null)
+        return entry.bind(closure);
+      return function(closure, arity, invoke) {
         return function(a1, a2, a3, a4) {
           return invoke(closure, arity, a1, a2, a3, a4);
         };
-      }(closure, arity, A.invokeClosure);
-      closure.$identity = $function;
-      return $function;
+      }(closure, arity, A._invokeClosure);
     },
     Closure_fromTearOff(parameters) {
       var $prototype, $constructor, t2, trampoline, applyTrampoline, i, stub, stub0, stubName, stubCallName,
@@ -1221,7 +1307,7 @@
       throw A.wrapException(new A._AssertionError(message));
     },
     throwCyclicInit(staticName) {
-      throw A.wrapException(new A.CyclicInitializationError(staticName));
+      throw A.wrapException(new A._CyclicInitializationError(staticName));
     },
     getIsolateAffinityTag($name) {
       return init.getIsolateTag($name);
@@ -1350,7 +1436,7 @@
         transformers = dartNativeDispatchHooksTransformer;
         if (typeof transformers == "function")
           transformers = [transformers];
-        if (transformers.constructor == Array)
+        if (Array.isArray(transformers))
           for (i = 0; i < transformers.length; ++i) {
             transformer = transformers[i];
             if (typeof transformer == "function")
@@ -1367,6 +1453,17 @@
     applyHooksTransformer(transformer, hooks) {
       return transformer(hooks) || hooks;
     },
+    createRecordTypePredicate(shape, fieldRtis) {
+      var $length = fieldRtis.length,
+        $function = init.rttc["" + $length + ";" + shape];
+      if ($function == null)
+        return null;
+      if ($length === 0)
+        return $function;
+      if ($length === $function.length)
+        return $function.apply(null, fieldRtis);
+      return $function(fieldRtis);
+    },
     JSSyntaxRegExp_makeNative(source, multiLine, caseSensitive, unicode, dotAll, global) {
       var m = multiLine ? "m" : "",
         i = caseSensitive ? "" : "i",
@@ -1434,7 +1531,7 @@
       return t1.charCodeAt(0) == 0 ? t1 : t1;
     },
     stringReplaceAllUncheckedString(receiver, pattern, replacement) {
-      var $length, t1, i, index;
+      var $length, t1, i;
       if (pattern === "") {
         if (receiver === "")
           return replacement;
@@ -1444,8 +1541,7 @@
           t1 = t1 + receiver[i] + replacement;
         return t1.charCodeAt(0) == 0 ? t1 : t1;
       }
-      index = receiver.indexOf(pattern, 0);
-      if (index < 0)
+      if (receiver.indexOf(pattern, 0) < 0)
         return receiver;
       if (receiver.length < 500 || replacement.indexOf("$", 0) >= 0)
         return receiver.split(pattern).join(replacement);
@@ -1477,17 +1573,23 @@
     },
     ConstantMap: function ConstantMap() {
     },
-    ConstantStringMap: function ConstantStringMap(t0, t1, t2, t3) {
-      var _ = this;
-      _._length = t0;
-      _._jsObject = t1;
-      _.__js_helper$_keys = t2;
-      _.$ti = t3;
+    ConstantStringMap: function ConstantStringMap(t0, t1, t2) {
+      this._jsIndex = t0;
+      this._values = t1;
+      this.$ti = t2;
     },
-    _ConstantMapKeyIterable: function _ConstantMapKeyIterable(t0, t1) {
-      this._map = t0;
+    _KeysOrValues: function _KeysOrValues(t0, t1) {
+      this._elements = t0;
       this.$ti = t1;
     },
+    _KeysOrValuesOrElementsIterator: function _KeysOrValuesOrElementsIterator(t0, t1, t2) {
+      var _ = this;
+      _._elements = t0;
+      _._length = t1;
+      _.__js_helper$_index = 0;
+      _.__js_helper$_current = null;
+      _.$ti = t2;
+    },
     Instantiation: function Instantiation() {
     },
     Instantiation1: function Instantiation1(t0, t1) {
@@ -1531,10 +1633,6 @@
     NullThrownFromJavaScriptException: function NullThrownFromJavaScriptException(t0) {
       this._irritant = t0;
     },
-    ExceptionAndStackTrace: function ExceptionAndStackTrace(t0, t1) {
-      this.dartException = t0;
-      this.stackTrace = t1;
-    },
     _StackTrace: function _StackTrace(t0) {
       this._exception = t0;
       this._trace = null;
@@ -1553,6 +1651,9 @@
       this._receiver = t0;
       this._interceptor = t1;
     },
+    _CyclicInitializationError: function _CyclicInitializationError(t0) {
+      this.variableName = t0;
+    },
     RuntimeError: function RuntimeError(t0) {
       this.message = t0;
     },
@@ -1609,7 +1710,7 @@
     _AllMatchesIterable: function _AllMatchesIterable(t0, t1, t2) {
       this._re = t0;
       this.__js_helper$_string = t1;
-      this._start = t2;
+      this.__js_helper$_start = t2;
     },
     _AllMatchesIterator: function _AllMatchesIterator(t0, t1, t2) {
       var _ = this;
@@ -1635,21 +1736,30 @@
       _.__js_helper$_current = null;
     },
     throwLateFieldNI(fieldName) {
-      return A.throwExpression(A.LateError$fieldNI(fieldName));
+      A.throwExpressionWithWrapper(new A.LateError("Field '" + fieldName + "' has not been initialized."), new Error());
     },
     throwLateFieldAI(fieldName) {
-      return A.throwExpression(A.LateError$fieldAI(fieldName));
+      A.throwExpressionWithWrapper(new A.LateError("Field '" + fieldName + "' has already been initialized."), new Error());
     },
     throwLateFieldADI(fieldName) {
-      return A.throwExpression(A.LateError$fieldADI(fieldName));
+      A.throwExpressionWithWrapper(new A.LateError("Field '" + fieldName + string$.x27_has_), new Error());
     },
     _Cell$named(_name) {
       var t1 = new A._Cell(_name);
-      return t1.__late_helper$_value = t1;
+      return t1._value = t1;
+    },
+    _InitializedCell$named(_name, _initializer) {
+      var t1 = new A._InitializedCell(_name, _initializer);
+      return t1._value = t1;
     },
     _Cell: function _Cell(t0) {
       this.__late_helper$_name = t0;
-      this.__late_helper$_value = null;
+      this._value = null;
+    },
+    _InitializedCell: function _InitializedCell(t0, t1) {
+      this.__late_helper$_name = t0;
+      this._value = null;
+      this._initializer = t1;
     },
     _ensureNativeList(list) {
       return list;
@@ -1671,14 +1781,22 @@
         throw A.wrapException(A.diagnoseRangeError(start, end, $length));
       return end;
     },
+    NativeByteBuffer: function NativeByteBuffer() {
+    },
     NativeTypedData: function NativeTypedData() {
     },
+    NativeByteData: function NativeByteData() {
+    },
     NativeTypedArray: function NativeTypedArray() {
     },
     NativeTypedArrayOfDouble: function NativeTypedArrayOfDouble() {
     },
     NativeTypedArrayOfInt: function NativeTypedArrayOfInt() {
     },
+    NativeFloat32List: function NativeFloat32List() {
+    },
+    NativeFloat64List: function NativeFloat64List() {
+    },
     NativeInt16List: function NativeInt16List() {
     },
     NativeInt32List: function NativeInt32List() {
@@ -1713,7 +1831,7 @@
       var kind = rti._kind;
       if (kind === 6 || kind === 7 || kind === 8)
         return A.Rti__isUnionOfFunctionType(rti._primary);
-      return kind === 11 || kind === 12;
+      return kind === 12 || kind === 13;
     },
     Rti__getCanonicalRecipe(rti) {
       return rti._canonicalRecipe;
@@ -1779,7 +1897,7 @@
           if (substitutedBase === base && substitutedArguments === $arguments)
             return rti;
           return A._Universe__lookupBindingRti(universe, substitutedBase, substitutedArguments);
-        case 11:
+        case 12:
           returnType = rti._primary;
           substitutedReturnType = A._substitute(universe, returnType, typeArguments, depth);
           functionParameters = rti._rest;
@@ -1787,7 +1905,7 @@
           if (substitutedReturnType === returnType && substitutedFunctionParameters === functionParameters)
             return rti;
           return A._Universe__lookupFunctionRti(universe, substitutedReturnType, substitutedFunctionParameters);
-        case 12:
+        case 13:
           bounds = rti._rest;
           depth += bounds.length;
           substitutedBounds = A._substituteArray(universe, bounds, typeArguments, depth);
@@ -1796,7 +1914,7 @@
           if (substitutedBounds === bounds && substitutedBase === base)
             return rti;
           return A._Universe__lookupGenericFunctionRti(universe, substitutedBase, substitutedBounds, true);
-        case 13:
+        case 14:
           index = rti._primary;
           if (index < depth)
             return rti;
@@ -1857,11 +1975,13 @@
       return target;
     },
     closureFunctionType(closure) {
-      var signature = closure.$signature;
+      var t1,
+        signature = closure.$signature;
       if (signature != null) {
         if (typeof signature == "number")
           return A.getTypeFromTypesTable(signature);
-        return closure.$signature();
+        t1 = closure.$signature();
+        return t1;
       }
       return null;
     },
@@ -1876,11 +1996,8 @@
       return A.instanceType(object);
     },
     instanceType(object) {
-      var rti;
-      if (object instanceof A.Object) {
-        rti = object.$ti;
-        return rti != null ? rti : A._instanceTypeFromConstructor(object);
-      }
+      if (object instanceof A.Object)
+        return A._instanceType(object);
       if (Array.isArray(object))
         return A._arrayInstanceType(object);
       return A._instanceTypeFromConstructor(J.getInterceptor$(object));
@@ -1906,7 +2023,7 @@
       return A._instanceTypeFromConstructorMiss(instance, $constructor);
     },
     _instanceTypeFromConstructorMiss(instance, $constructor) {
-      var effectiveConstructor = instance instanceof A.Closure ? instance.__proto__.__proto__.constructor : $constructor,
+      var effectiveConstructor = instance instanceof A.Closure ? Object.getPrototypeOf(Object.getPrototypeOf(instance)).constructor : $constructor,
         rti = A._Universe_findErasedType(init.typeUniverse, effectiveConstructor.name);
       $constructor.$ccache = rti;
       return rti;
@@ -1922,28 +2039,42 @@
       }
       return type;
     },
-    getRuntimeType(object) {
-      var rti = object instanceof A.Closure ? A.closureFunctionType(object) : null;
-      return A.createRuntimeType(rti == null ? A.instanceType(object) : rti);
+    getRuntimeTypeOfDartObject(object) {
+      return A.createRuntimeType(A._instanceType(object));
+    },
+    getRuntimeTypeOfClosure(closure) {
+      var rti = A.closureFunctionType(closure);
+      return A.createRuntimeType(rti == null ? A.instanceType(closure) : rti);
+    },
+    _structuralTypeOf(object) {
+      var functionRti = object instanceof A.Closure ? A.closureFunctionType(object) : null;
+      if (functionRti != null)
+        return functionRti;
+      if (type$.TrustedGetRuntimeType._is(object))
+        return J.get$runtimeType$(object)._rti;
+      if (Array.isArray(object))
+        return A._arrayInstanceType(object);
+      return A.instanceType(object);
     },
     createRuntimeType(rti) {
-      var recipe, starErasedRecipe, starErasedRti,
-        type = rti._cachedRuntimeType;
-      if (type != null)
-        return type;
-      recipe = rti._canonicalRecipe;
-      starErasedRecipe = recipe.replace(/\*/g, "");
-      if (starErasedRecipe === recipe)
+      var t1 = rti._cachedRuntimeType;
+      return t1 == null ? rti._cachedRuntimeType = A._createRuntimeType(rti) : t1;
+    },
+    _createRuntimeType(rti) {
+      var starErasedRti, t1,
+        s = rti._canonicalRecipe,
+        starErasedRecipe = s.replace(/\*/g, "");
+      if (starErasedRecipe === s)
         return rti._cachedRuntimeType = new A._Type(rti);
       starErasedRti = A._Universe_eval(init.typeUniverse, starErasedRecipe, true);
-      type = starErasedRti._cachedRuntimeType;
-      return rti._cachedRuntimeType = type == null ? starErasedRti._cachedRuntimeType = new A._Type(starErasedRti) : type;
+      t1 = starErasedRti._cachedRuntimeType;
+      return t1 == null ? starErasedRti._cachedRuntimeType = A._createRuntimeType(starErasedRti) : t1;
     },
     typeLiteral(recipe) {
       return A.createRuntimeType(A._Universe_eval(init.typeUniverse, recipe, false));
     },
     _installSpecializedIsTest(object) {
-      var t1, unstarred, isFn, $name, testRti = this;
+      var t1, unstarred, isFn, $name, predicate, testRti = this;
       if (testRti === type$.Object)
         return A._finishIsFn(testRti, object, A._isObject);
       if (!A.isStrongTopType(testRti))
@@ -1956,7 +2087,14 @@
       if (t1)
         return A._finishIsFn(testRti, object, A._isTop);
       t1 = testRti._kind;
+      if (t1 === 7)
+        return A._finishIsFn(testRti, object, A._generalNullableIsTestImplementation);
+      if (t1 === 1)
+        return A._finishIsFn(testRti, object, A._isNever);
       unstarred = t1 === 6 ? testRti._primary : testRti;
+      t1 = unstarred._kind;
+      if (t1 === 8)
+        return A._finishIsFn(testRti, object, A._isFutureOr);
       if (unstarred === type$.int)
         isFn = A._isInt;
       else if (unstarred === type$.double || unstarred === type$.num)
@@ -1967,7 +2105,7 @@
         isFn = unstarred === type$.bool ? A._isBool : null;
       if (isFn != null)
         return A._finishIsFn(testRti, object, isFn);
-      if (unstarred._kind === 9) {
+      if (t1 === 9) {
         $name = unstarred._primary;
         if (unstarred._rest.every(A.isTopType)) {
           testRti._specializedTestResource = "$is" + $name;
@@ -1975,8 +2113,10 @@
             return A._finishIsFn(testRti, object, A._isListTestViaProperty);
           return A._finishIsFn(testRti, object, A._isTestViaProperty);
         }
-      } else if (t1 === 7)
-        return A._finishIsFn(testRti, object, A._generalNullableIsTestImplementation);
+      } else if (t1 === 11) {
+        predicate = A.createRecordTypePredicate(unstarred._primary, unstarred._rest);
+        return A._finishIsFn(testRti, object, predicate == null ? A._isNever : predicate);
+      }
       return A._finishIsFn(testRti, object, A._generalIsTestImplementation);
     },
     _finishIsFn(testRti, object, isFn) {
@@ -2012,7 +2152,10 @@
         if (!(testRti === type$.legacy_Object))
           if (!(testRti === type$.legacy_Never))
             if (kind !== 7)
-              t1 = kind === 8 && A._nullIs(testRti._primary) || testRti === type$.Null || testRti === type$.JSNull;
+              if (!(kind === 6 && A._nullIs(testRti._primary)))
+                t1 = kind === 8 && A._nullIs(testRti._primary) || testRti === type$.Null || testRti === type$.JSNull;
+              else
+                t1 = true;
             else
               t1 = true;
           else
@@ -2075,7 +2218,7 @@
       A._failedAsCheck(object, testRti);
     },
     _failedAsCheck(object, testRti) {
-      throw A.wrapException(A._TypeError$fromMessage(A._Error_compose(object, A.instanceOrFunctionType(object, testRti), A._rtiToString(testRti, null))));
+      throw A.wrapException(A._TypeError$fromMessage(A._Error_compose(object, A._rtiToString(testRti, null))));
     },
     checkTypeBound(type, bound, variable, methodName) {
       var _null = null;
@@ -2083,15 +2226,19 @@
         return type;
       throw A.wrapException(A._TypeError$fromMessage("The type argument '" + A._rtiToString(type, _null) + "' is not a subtype of the type variable bound '" + A._rtiToString(bound, _null) + "' of type variable '" + variable + "' in '" + methodName + "'."));
     },
-    _Error_compose(object, objectRti, checkedTypeDescription) {
-      var objectDescription = A.Error_safeToString(object);
-      return objectDescription + ": type '" + A._rtiToString(objectRti == null ? A.instanceType(object) : objectRti, null) + "' is not a subtype of type '" + checkedTypeDescription + "'";
+    _Error_compose(object, checkedTypeDescription) {
+      return A.Error_safeToString(object) + ": type '" + A._rtiToString(A._structuralTypeOf(object), null) + "' is not a subtype of type '" + checkedTypeDescription + "'";
     },
     _TypeError$fromMessage(message) {
       return new A._TypeError("TypeError: " + message);
     },
     _TypeError__TypeError$forType(object, type) {
-      return new A._TypeError("TypeError: " + A._Error_compose(object, null, type));
+      return new A._TypeError("TypeError: " + A._Error_compose(object, type));
+    },
+    _isFutureOr(object) {
+      var testRti = this,
+        unstarred = testRti._kind === 6 ? testRti._primary : testRti;
+      return unstarred._primary._is(object) || A.Rti__getFutureFromFutureOr(init.typeUniverse, unstarred)._is(object);
     },
     _isObject(object) {
       return object != null;
@@ -2107,6 +2254,9 @@
     _asTop(object) {
       return object;
     },
+    _isNever(object) {
+      return false;
+    },
     _isBool(object) {
       return true === object || false === object;
     },
@@ -2226,6 +2376,26 @@
         s += sep + A._rtiToString(array[i], genericContext);
       return s;
     },
+    _recordRtiToString(recordType, genericContext) {
+      var fieldCount, names, namesIndex, s, comma, i,
+        partialShape = recordType._primary,
+        fields = recordType._rest;
+      if ("" === partialShape)
+        return "(" + A._rtiArrayToString(fields, genericContext) + ")";
+      fieldCount = fields.length;
+      names = partialShape.split(",");
+      namesIndex = names.length - fieldCount;
+      for (s = "(", comma = "", i = 0; i < fieldCount; ++i, comma = ", ") {
+        s += comma;
+        if (namesIndex === 0)
+          s += "{";
+        s += A._rtiToString(fields[i], genericContext);
+        if (namesIndex >= 0)
+          s += " " + names[namesIndex];
+        ++namesIndex;
+      }
+      return s + "})";
+    },
     _functionRtiToString(functionType, genericContext, bounds) {
       var boundsLength, outerContextLength, offset, i, t1, t2, typeParametersText, typeSep, t3, t4, boundRti, kind, parameters, requiredPositional, requiredPositionalLength, optionalPositional, optionalPositionalLength, named, namedLength, returnTypeText, argumentsText, sep, _s2_ = ", ";
       if (bounds != null) {
@@ -2315,7 +2485,7 @@
         questionArgument = rti._primary;
         s = A._rtiToString(questionArgument, genericContext);
         argumentKind = questionArgument._kind;
-        return (argumentKind === 11 || argumentKind === 12 ? "(" + s + ")" : s) + "?";
+        return (argumentKind === 12 || argumentKind === 13 ? "(" + s + ")" : s) + "?";
       }
       if (kind === 8)
         return "FutureOr<" + A._rtiToString(rti._primary, genericContext) + ">";
@@ -2325,10 +2495,12 @@
         return $arguments.length > 0 ? $name + ("<" + A._rtiArrayToString($arguments, genericContext) + ">") : $name;
       }
       if (kind === 11)
-        return A._functionRtiToString(rti, genericContext, null);
+        return A._recordRtiToString(rti, genericContext);
       if (kind === 12)
+        return A._functionRtiToString(rti, genericContext, null);
+      if (kind === 13)
         return A._functionRtiToString(rti._primary, genericContext, rti._rest);
-      if (kind === 13) {
+      if (kind === 14) {
         t1 = rti._primary;
         t2 = genericContext.length;
         t1 = t2 - 1 - t1;
@@ -2536,7 +2708,7 @@
       if (probe != null)
         return probe;
       rti = new A.Rti(null, null);
-      rti._kind = 13;
+      rti._kind = 14;
       rti._primary = index;
       rti._canonicalRecipe = key;
       t1 = A._Universe__installTypeTests(universe, rti);
@@ -2601,6 +2773,21 @@
       universe.eC.set(key, t1);
       return t1;
     },
+    _Universe__lookupRecordRti(universe, partialShapeTag, fields) {
+      var rti, t1,
+        key = "+" + (partialShapeTag + "(" + A._Universe__canonicalRecipeJoin(fields) + ")"),
+        probe = universe.eC.get(key);
+      if (probe != null)
+        return probe;
+      rti = new A.Rti(null, null);
+      rti._kind = 11;
+      rti._primary = partialShapeTag;
+      rti._rest = fields;
+      rti._canonicalRecipe = key;
+      t1 = A._Universe__installTypeTests(universe, rti);
+      universe.eC.set(key, t1);
+      return t1;
+    },
     _Universe__lookupFunctionRti(universe, returnType, parameters) {
       var sep, key, probe, rti, t1,
         s = returnType._canonicalRecipe,
@@ -2624,7 +2811,7 @@
       if (probe != null)
         return probe;
       rti = new A.Rti(null, null);
-      rti._kind = 11;
+      rti._kind = 12;
       rti._primary = returnType;
       rti._rest = parameters;
       rti._canonicalRecipe = key;
@@ -2661,7 +2848,7 @@
         }
       }
       rti = new A.Rti(null, null);
-      rti._kind = 12;
+      rti._kind = 13;
       rti._primary = baseFunctionType;
       rti._rest = bounds;
       rti._canonicalRecipe = key;
@@ -2671,14 +2858,14 @@
       return {u: universe, e: environment, r: recipe, s: [], p: 0, n: normalize};
     },
     _Parser_parse(parser) {
-      var t2, i, ch, t3, array, head, base, parameters, optionalPositional, named, item,
+      var t2, i, ch, t3, array, end, item,
         source = parser.r,
         t1 = parser.s;
       for (t2 = source.length, i = 0; i < t2;) {
         ch = source.charCodeAt(i);
         if (ch >= 48 && ch <= 57)
           i = A._Parser_handleDigit(i + 1, ch, source, t1);
-        else if ((((ch | 32) >>> 0) - 97 & 65535) < 26 || ch === 95 || ch === 36)
+        else if ((((ch | 32) >>> 0) - 97 & 65535) < 26 || ch === 95 || ch === 36 || ch === 124)
           i = A._Parser_handleIdentifier(parser, i, source, t1, false);
         else if (ch === 46)
           i = A._Parser_handleIdentifier(parser, i, source, t1, true);
@@ -2713,24 +2900,7 @@
               parser.p = t1.length;
               break;
             case 62:
-              t3 = parser.u;
-              array = t1.splice(parser.p);
-              A._Parser_toTypes(parser.u, parser.e, array);
-              parser.p = t1.pop();
-              head = t1.pop();
-              if (typeof head == "string")
-                t1.push(A._Universe__lookupInterfaceRti(t3, head, array));
-              else {
-                base = A._Parser_toType(t3, parser.e, head);
-                switch (base._kind) {
-                  case 11:
-                    t1.push(A._Universe__lookupGenericFunctionRti(t3, base, array, parser.n));
-                    break;
-                  default:
-                    t1.push(A._Universe__lookupBindingRti(t3, base, array));
-                    break;
-                }
-              }
+              A._Parser_handleTypeArguments(parser, t1);
               break;
             case 38:
               A._Parser_handleExtendedOperations(parser, t1);
@@ -2748,36 +2918,12 @@
               t1.push(A._Universe__lookupFutureOrRti(t3, A._Parser_toType(t3, parser.e, t1.pop()), parser.n));
               break;
             case 40:
+              t1.push(-3);
               t1.push(parser.p);
               parser.p = t1.length;
               break;
             case 41:
-              t3 = parser.u;
-              parameters = new A._FunctionParameters();
-              optionalPositional = t3.sEA;
-              named = t3.sEA;
-              head = t1.pop();
-              if (typeof head == "number")
-                switch (head) {
-                  case -1:
-                    optionalPositional = t1.pop();
-                    break;
-                  case -2:
-                    named = t1.pop();
-                    break;
-                  default:
-                    t1.push(head);
-                    break;
-                }
-              else
-                t1.push(head);
-              array = t1.splice(parser.p);
-              A._Parser_toTypes(parser.u, parser.e, array);
-              parser.p = t1.pop();
-              parameters._requiredPositional = array;
-              parameters._optionalPositional = optionalPositional;
-              parameters._named = named;
-              t1.push(A._Universe__lookupFunctionRti(t3, A._Parser_toType(t3, parser.e, t1.pop()), parameters));
+              A._Parser_handleArguments(parser, t1);
               break;
             case 91:
               t1.push(parser.p);
@@ -2801,6 +2947,14 @@
               t1.push(array);
               t1.push(-2);
               break;
+            case 43:
+              end = source.indexOf("(", i);
+              t1.push(source.substring(i, end));
+              t1.push(-4);
+              t1.push(parser.p);
+              parser.p = t1.length;
+              i = end + 1;
+              break;
             default:
               throw "Bad character " + ch;
           }
@@ -2831,7 +2985,7 @@
             break;
           hasPeriod = true;
         } else {
-          if (!((((ch | 32) >>> 0) - 97 & 65535) < 26 || ch === 95 || ch === 36))
+          if (!((((ch | 32) >>> 0) - 97 & 65535) < 26 || ch === 95 || ch === 36 || ch === 124))
             t2 = ch >= 48 && ch <= 57;
           else
             t2 = true;
@@ -2853,6 +3007,73 @@
         stack.push(string);
       return i;
     },
+    _Parser_handleTypeArguments(parser, stack) {
+      var base,
+        t1 = parser.u,
+        $arguments = A._Parser_collectArray(parser, stack),
+        head = stack.pop();
+      if (typeof head == "string")
+        stack.push(A._Universe__lookupInterfaceRti(t1, head, $arguments));
+      else {
+        base = A._Parser_toType(t1, parser.e, head);
+        switch (base._kind) {
+          case 12:
+            stack.push(A._Universe__lookupGenericFunctionRti(t1, base, $arguments, parser.n));
+            break;
+          default:
+            stack.push(A._Universe__lookupBindingRti(t1, base, $arguments));
+            break;
+        }
+      }
+    },
+    _Parser_handleArguments(parser, stack) {
+      var optionalPositional, named, requiredPositional, returnType, parameters, _null = null,
+        t1 = parser.u,
+        head = stack.pop();
+      if (typeof head == "number")
+        switch (head) {
+          case -1:
+            optionalPositional = stack.pop();
+            named = _null;
+            break;
+          case -2:
+            named = stack.pop();
+            optionalPositional = _null;
+            break;
+          default:
+            stack.push(head);
+            named = _null;
+            optionalPositional = named;
+            break;
+        }
+      else {
+        stack.push(head);
+        named = _null;
+        optionalPositional = named;
+      }
+      requiredPositional = A._Parser_collectArray(parser, stack);
+      head = stack.pop();
+      switch (head) {
+        case -3:
+          head = stack.pop();
+          if (optionalPositional == null)
+            optionalPositional = t1.sEA;
+          if (named == null)
+            named = t1.sEA;
+          returnType = A._Parser_toType(t1, parser.e, head);
+          parameters = new A._FunctionParameters();
+          parameters._requiredPositional = requiredPositional;
+          parameters._optionalPositional = optionalPositional;
+          parameters._named = named;
+          stack.push(A._Universe__lookupFunctionRti(t1, returnType, parameters));
+          return;
+        case -4:
+          stack.push(A._Universe__lookupRecordRti(t1, stack.pop(), requiredPositional));
+          return;
+        default:
+          throw A.wrapException(A.AssertionError$("Unexpected state under `()`: " + A.S(head)));
+      }
+    },
     _Parser_handleExtendedOperations(parser, stack) {
       var $top = stack.pop();
       if (0 === $top) {
@@ -2865,6 +3086,12 @@
       }
       throw A.wrapException(A.AssertionError$("Unexpected extended operation " + A.S($top)));
     },
+    _Parser_collectArray(parser, stack) {
+      var array = stack.splice(parser.p);
+      A._Parser_toTypes(parser.u, parser.e, array);
+      parser.p = stack.pop();
+      return array;
+    },
     _Parser_toType(universe, environment, item) {
       if (typeof item == "string")
         return A._Universe__lookupInterfaceRti(universe, item, universe.sEA);
@@ -2909,7 +3136,7 @@
       throw A.wrapException(A.AssertionError$("Bad index " + index + " for " + environment.toString$0(0)));
     },
     _isSubtype(universe, s, sEnv, t, tEnv) {
-      var t1, sKind, leftTypeVariable, tKind, sBounds, tBounds, sLength, i, sBound, tBound;
+      var t1, sKind, leftTypeVariable, tKind, t2, sBounds, tBounds, sLength, i, sBound, tBound;
       if (s === t)
         return true;
       if (!A.isStrongTopType(t))
@@ -2932,7 +3159,7 @@
         t1 = true;
       if (t1)
         return true;
-      leftTypeVariable = sKind === 13;
+      leftTypeVariable = sKind === 14;
       if (leftTypeVariable)
         if (A._isSubtype(universe, sEnv[s._primary], sEnv, t, tEnv))
           return true;
@@ -2976,13 +3203,16 @@
       }
       if (leftTypeVariable)
         return false;
-      t1 = sKind !== 11;
-      if ((!t1 || sKind === 12) && t === type$.Function)
+      t1 = sKind !== 12;
+      if ((!t1 || sKind === 13) && t === type$.Function)
         return true;
-      if (tKind === 12) {
+      t2 = sKind === 11;
+      if (t2 && t === type$.Record)
+        return true;
+      if (tKind === 13) {
         if (s === type$.JavaScriptFunction)
           return true;
-        if (sKind !== 12)
+        if (sKind !== 13)
           return false;
         sBounds = s._rest;
         tBounds = t._rest;
@@ -2999,7 +3229,7 @@
         }
         return A._isFunctionSubtype(universe, s._primary, sEnv, t._primary, tEnv);
       }
-      if (tKind === 11) {
+      if (tKind === 12) {
         if (s === type$.JavaScriptFunction)
           return true;
         if (t1)
@@ -3011,6 +3241,8 @@
           return false;
         return A._isInterfaceSubtype(universe, s, sEnv, t, tEnv);
       }
+      if (t2 && tKind === 11)
+        return A._isRecordSubtype(universe, s, sEnv, t, tEnv);
       return false;
     },
     _isFunctionSubtype(universe, s, sEnv, t, tEnv) {
@@ -3118,6 +3350,20 @@
       }
       return true;
     },
+    _isRecordSubtype(universe, s, sEnv, t, tEnv) {
+      var i,
+        sFields = s._rest,
+        tFields = t._rest,
+        sCount = sFields.length;
+      if (sCount !== tFields.length)
+        return false;
+      if (s._primary !== t._primary)
+        return false;
+      for (i = 0; i < sCount; ++i)
+        if (!A._isSubtype(universe, sFields[i], sEnv, tFields[i], tEnv))
+          return false;
+      return true;
+    },
     isNullable(t) {
       var t1,
         kind = t._kind;
@@ -3223,56 +3469,6 @@
       t1._TimerImpl$periodic$2(milliseconds, callback);
       return t1;
     },
-    _makeAsyncAwaitCompleter($T) {
-      return new A._AsyncAwaitCompleter(new A._Future($.Zone__current, $T._eval$1("_Future<0>")), $T._eval$1("_AsyncAwaitCompleter<0>"));
-    },
-    _asyncStartSync(bodyFunction, completer) {
-      bodyFunction.call$2(0, null);
-      completer.isSync = true;
-      return completer._future;
-    },
-    _asyncAwait(object, bodyFunction) {
-      A._awaitOnObject(object, bodyFunction);
-    },
-    _asyncReturn(object, completer) {
-      completer.complete$1(0, object);
-    },
-    _asyncRethrow(object, completer) {
-      completer.completeError$2(A.unwrapException(object), A.getTraceFromException(object));
-    },
-    _awaitOnObject(object, bodyFunction) {
-      var t1, future,
-        thenCallback = new A._awaitOnObject_closure(bodyFunction),
-        errorCallback = new A._awaitOnObject_closure0(bodyFunction);
-      if (object instanceof A._Future)
-        object._thenAwait$1$2(thenCallback, errorCallback, type$.dynamic);
-      else {
-        t1 = type$.dynamic;
-        if (type$.Future_dynamic._is(object))
-          object.then$1$2$onError(thenCallback, errorCallback, t1);
-        else {
-          future = new A._Future($.Zone__current, type$._Future_dynamic);
-          future._async$_state = 8;
-          future._resultOrListeners = object;
-          future._thenAwait$1$2(thenCallback, errorCallback, t1);
-        }
-      }
-    },
-    _wrapJsFunctionForAsync($function) {
-      var $protected = function(fn, ERROR) {
-        return function(errorCode, result) {
-          while (true)
-            try {
-              fn(errorCode, result);
-              break;
-            } catch (error) {
-              result = error;
-              errorCode = ERROR;
-            }
-        };
-      }($function, 1);
-      return $.Zone__current.registerBinaryCallback$3$1(new A._wrapJsFunctionForAsync_closure($protected), type$.void, type$.int, type$.dynamic);
-    },
     AsyncError$(error, stackTrace) {
       var t1 = A.checkNotNullable(error, "error", type$.Object);
       return new A.AsyncError(t1, stackTrace == null ? A.AsyncError_defaultStackTrace(error) : stackTrace);
@@ -3287,14 +3483,13 @@
       return B._StringStackTrace_3uE;
     },
     Future_Future$value(value, $T) {
-      var t1, t2;
+      var t1;
       $T._as(value);
-      t1 = value;
-      t2 = new A._Future($.Zone__current, $T._eval$1("_Future<0>"));
-      t2._asyncComplete$1(t1);
-      return t2;
+      t1 = new A._Future($.Zone__current, $T._eval$1("_Future<0>"));
+      t1._asyncComplete$1(value);
+      return t1;
     },
-    _Future__chainCoreFuture(source, target) {
+    _Future__chainCoreFutureSync(source, target) {
       var t1, t2, listeners;
       for (t1 = type$._Future_dynamic; t2 = source._async$_state, (t2 & 4) !== 0;)
         source = t1._as(source._resultOrListeners);
@@ -3304,11 +3499,30 @@
         A._Future__propagateToListeners(target, listeners);
       } else {
         listeners = type$.nullable__FutureListener_dynamic_dynamic._as(target._resultOrListeners);
-        target._async$_state = target._async$_state & 1 | 4;
-        target._resultOrListeners = source;
+        target._setChained$1(source);
         source._prependListeners$1(listeners);
       }
     },
+    _Future__chainCoreFutureAsync(source, target) {
+      var t2, t3, listeners, _box_0 = {},
+        t1 = _box_0.source = source;
+      for (t2 = type$._Future_dynamic; t3 = t1._async$_state, (t3 & 4) !== 0; t1 = source) {
+        source = t2._as(t1._resultOrListeners);
+        _box_0.source = source;
+      }
+      if ((t3 & 24) === 0) {
+        listeners = type$.nullable__FutureListener_dynamic_dynamic._as(target._resultOrListeners);
+        target._setChained$1(t1);
+        _box_0.source._prependListeners$1(listeners);
+        return;
+      }
+      if ((t3 & 16) === 0 && target._resultOrListeners == null) {
+        target._cloneResult$1(t1);
+        return;
+      }
+      target._async$_state ^= 2;
+      target._zone.scheduleMicrotask$1(new A._Future__chainCoreFutureAsync_closure(_box_0, target));
+    },
     _Future__propagateToListeners(source, listeners) {
       var t2, t3, t4, _box_0, t5, t6, hasError, asyncError, nextListener, nextListener0, sourceResult, t7, zone, oldZone, result, current, _box_1 = {},
         t1 = _box_1.source = source;
@@ -3370,7 +3584,7 @@
           if (oldZone != null)
             $.Zone__current = oldZone;
           t1 = _box_0.listenerValueOrError;
-          if (t4._is(t1)) {
+          if (t1 instanceof A._Future) {
             t5 = _box_0.listener.$ti;
             t5 = t5._eval$1("Future<2>")._is(t1) || !t5._rest[1]._is(t1);
           } else
@@ -3387,7 +3601,7 @@
               _box_1.source = t1;
               continue;
             } else
-              A._Future__chainCoreFuture(t1, result);
+              A._Future__chainCoreFutureSync(t1, result);
             return;
           }
         }
@@ -3488,10 +3702,6 @@
       t1 = $.Zone__current;
       t1.scheduleMicrotask$1(t1.bindCallbackGuarded$1(callback));
     },
-    StreamIterator_StreamIterator(stream, $T) {
-      A.checkNotNullable(stream, "stream", type$.Object);
-      return new A._StreamIterator($T._eval$1("_StreamIterator<0>"));
-    },
     StreamController_StreamController(onCancel, onListen, sync, $T) {
       return new A._SyncStreamController(onListen, null, null, onCancel, $T._eval$1("_SyncStreamController<0>"));
     },
@@ -3649,7 +3859,6 @@
       type$.nullable_Map_of_nullable_Object_and_nullable_Object._as(zoneValues);
       $.printToZone = A.async___printToZone$closure();
       valueMap = zone.get$_async$_map();
-      valueMap = valueMap;
       t1 = new A._CustomZone(zone.get$_run(), zone.get$_runUnary(), zone.get$_runBinary(), zone.get$_registerCallback(), zone.get$_registerUnaryCallback(), zone.get$_registerBinaryCallback(), zone.get$_errorCallback(), zone.get$_scheduleMicrotask(), zone.get$_createTimer(), zone.get$_createPeriodicTimer(), zone.get$_print(), zone.get$_fork(), zone.get$_handleUncaughtError(), zone, valueMap);
       handleUncaughtError = specification.handleUncaughtError;
       if (handleUncaughtError != null)
@@ -3704,20 +3913,6 @@
       _.start = t2;
       _.callback = t3;
     },
-    _AsyncAwaitCompleter: function _AsyncAwaitCompleter(t0, t1) {
-      this._future = t0;
-      this.isSync = false;
-      this.$ti = t1;
-    },
-    _awaitOnObject_closure: function _awaitOnObject_closure(t0) {
-      this.bodyFunction = t0;
-    },
-    _awaitOnObject_closure0: function _awaitOnObject_closure0(t0) {
-      this.bodyFunction = t0;
-    },
-    _wrapJsFunctionForAsync_closure: function _wrapJsFunctionForAsync_closure(t0) {
-      this.$protected = t0;
-    },
     AsyncError: function AsyncError(t0, t1) {
       this.error = t0;
       this.stackTrace = t1;
@@ -3767,11 +3962,11 @@
       this.e = t1;
       this.s = t2;
     },
-    _Future__asyncCompleteWithValue_closure: function _Future__asyncCompleteWithValue_closure(t0, t1) {
-      this.$this = t0;
-      this.value = t1;
+    _Future__chainCoreFutureAsync_closure: function _Future__chainCoreFutureAsync_closure(t0, t1) {
+      this._box_0 = t0;
+      this.target = t1;
     },
-    _Future__chainFuture_closure: function _Future__chainFuture_closure(t0, t1) {
+    _Future__asyncCompleteWithValue_closure: function _Future__asyncCompleteWithValue_closure(t0, t1) {
       this.$this = t0;
       this.value = t1;
     },
@@ -3813,8 +4008,6 @@
       this._box_0 = t0;
       this.future = t1;
     },
-    StreamTransformerBase: function StreamTransformerBase() {
-    },
     _StreamController: function _StreamController() {
     },
     _StreamController__subscribe_closure: function _StreamController__subscribe_closure(t0) {
@@ -3901,9 +4094,6 @@
       _._onDone = t1;
       _.$ti = t2;
     },
-    _StreamIterator: function _StreamIterator(t0) {
-      this.$ti = t0;
-    },
     _EmptyStream: function _EmptyStream(t0) {
       this.$ti = t0;
     },
@@ -4038,146 +4228,26 @@
       delete table["<non-identifier-key>"];
       return table;
     },
-    IterableBase_iterableToShortString(iterable, leftDelimiter, rightDelimiter) {
-      var parts, t1;
-      if (A._isToStringVisiting(iterable)) {
-        if (leftDelimiter === "(" && rightDelimiter === ")")
-          return "(...)";
-        return leftDelimiter + "..." + rightDelimiter;
-      }
-      parts = A._setArrayType([], type$.JSArray_String);
-      B.JSArray_methods.add$1($._toStringVisiting, iterable);
-      try {
-        A._iterablePartsToStrings(iterable, parts);
-      } finally {
-        if (0 >= $._toStringVisiting.length)
-          return A.ioore($._toStringVisiting, -1);
-        $._toStringVisiting.pop();
-      }
-      t1 = A.StringBuffer__writeAll(leftDelimiter, type$.Iterable_dynamic._as(parts), ", ") + rightDelimiter;
-      return t1.charCodeAt(0) == 0 ? t1 : t1;
-    },
-    IterableBase_iterableToFullString(iterable, leftDelimiter, rightDelimiter) {
-      var buffer, t1;
-      if (A._isToStringVisiting(iterable))
-        return leftDelimiter + "..." + rightDelimiter;
-      buffer = new A.StringBuffer(leftDelimiter);
-      B.JSArray_methods.add$1($._toStringVisiting, iterable);
-      try {
-        t1 = buffer;
-        t1._contents = A.StringBuffer__writeAll(t1._contents, iterable, ", ");
-      } finally {
-        if (0 >= $._toStringVisiting.length)
-          return A.ioore($._toStringVisiting, -1);
-        $._toStringVisiting.pop();
-      }
-      buffer._contents += rightDelimiter;
-      t1 = buffer._contents;
-      return t1.charCodeAt(0) == 0 ? t1 : t1;
-    },
-    _isToStringVisiting(o) {
-      var t1, i;
-      for (t1 = $._toStringVisiting.length, i = 0; i < t1; ++i)
-        if (o === $._toStringVisiting[i])
-          return true;
-      return false;
-    },
-    _iterablePartsToStrings(iterable, parts) {
-      var next, ultimateString, penultimateString, penultimate, ultimate, ultimate0, elision,
-        it = iterable.get$iterator(iterable),
-        $length = 0, count = 0;
-      while (true) {
-        if (!($length < 80 || count < 3))
-          break;
-        if (!it.moveNext$0())
-          return;
-        next = A.S(it.get$current(it));
-        B.JSArray_methods.add$1(parts, next);
-        $length += next.length + 2;
-        ++count;
-      }
-      if (!it.moveNext$0()) {
-        if (count <= 5)
-          return;
-        if (0 >= parts.length)
-          return A.ioore(parts, -1);
-        ultimateString = parts.pop();
-        if (0 >= parts.length)
-          return A.ioore(parts, -1);
-        penultimateString = parts.pop();
-      } else {
-        penultimate = it.get$current(it);
-        ++count;
-        if (!it.moveNext$0()) {
-          if (count <= 4) {
-            B.JSArray_methods.add$1(parts, A.S(penultimate));
-            return;
-          }
-          ultimateString = A.S(penultimate);
-          if (0 >= parts.length)
-            return A.ioore(parts, -1);
-          penultimateString = parts.pop();
-          $length += ultimateString.length + 2;
-        } else {
-          ultimate = it.get$current(it);
-          ++count;
-          for (; it.moveNext$0(); penultimate = ultimate, ultimate = ultimate0) {
-            ultimate0 = it.get$current(it);
-            ++count;
-            if (count > 100) {
-              while (true) {
-                if (!($length > 75 && count > 3))
-                  break;
-                if (0 >= parts.length)
-                  return A.ioore(parts, -1);
-                $length -= parts.pop().length + 2;
-                --count;
-              }
-              B.JSArray_methods.add$1(parts, "...");
-              return;
-            }
-          }
-          penultimateString = A.S(penultimate);
-          ultimateString = A.S(ultimate);
-          $length += ultimateString.length + penultimateString.length + 4;
-        }
-      }
-      if (count > parts.length + 2) {
-        $length += 5;
-        elision = "...";
-      } else
-        elision = null;
-      while (true) {
-        if (!($length > 80 && parts.length > 3))
-          break;
-        if (0 >= parts.length)
-          return A.ioore(parts, -1);
-        $length -= parts.pop().length + 2;
-        if (elision == null) {
-          $length += 5;
-          elision = "...";
-        }
-      }
-      if (elision != null)
-        B.JSArray_methods.add$1(parts, elision);
-      B.JSArray_methods.add$1(parts, penultimateString);
-      B.JSArray_methods.add$1(parts, ultimateString);
+    _LinkedHashSetIterator$(_set, _modifications, $E) {
+      var t1 = new A._LinkedHashSetIterator(_set, _modifications, $E._eval$1("_LinkedHashSetIterator<0>"));
+      t1._collection$_cell = _set._collection$_first;
+      return t1;
     },
     MapBase_mapToString(m) {
       var result, t1 = {};
-      if (A._isToStringVisiting(m))
+      if (A.isToStringVisiting(m))
         return "{...}";
       result = new A.StringBuffer("");
       try {
-        B.JSArray_methods.add$1($._toStringVisiting, m);
+        B.JSArray_methods.add$1($.toStringVisiting, m);
         result._contents += "{";
         t1.first = true;
         J.forEach$1$x(m, new A.MapBase_mapToString_closure(t1, result));
         result._contents += "}";
       } finally {
-        if (0 >= $._toStringVisiting.length)
-          return A.ioore($._toStringVisiting, -1);
-        $._toStringVisiting.pop();
+        if (0 >= $.toStringVisiting.length)
+          return A.ioore($.toStringVisiting, -1);
+        $.toStringVisiting.pop();
       }
       t1 = result._contents;
       return t1.charCodeAt(0) == 0 ? t1 : t1;
@@ -4224,20 +4294,14 @@
       _._collection$_current = _._collection$_cell = null;
       _.$ti = t2;
     },
-    IterableBase: function IterableBase() {
-    },
     ListBase: function ListBase() {
     },
-    ListMixin: function ListMixin() {
-    },
     MapBase: function MapBase() {
     },
     MapBase_mapToString_closure: function MapBase_mapToString_closure(t0, t1) {
       this._box_0 = t0;
       this.result = t1;
     },
-    MapMixin: function MapMixin() {
-    },
     _UnmodifiableMapMixin: function _UnmodifiableMapMixin() {
     },
     MapView: function MapView() {
@@ -4246,16 +4310,12 @@
       this._collection$_map = t0;
       this.$ti = t1;
     },
-    SetMixin: function SetMixin() {
+    SetBase: function SetBase() {
     },
     _SetBase: function _SetBase() {
     },
-    _ListBase_Object_ListMixin: function _ListBase_Object_ListMixin() {
-    },
     _UnmodifiableMapView_MapView__UnmodifiableMapMixin: function _UnmodifiableMapView_MapView__UnmodifiableMapMixin() {
     },
-    __SetBase_Object_SetMixin: function __SetBase_Object_SetMixin() {
-    },
     _parseJson(source, reviver) {
       var e, exception, t1, parsed = null;
       try {
@@ -4457,11 +4517,6 @@
         return value;
       throw A.wrapException(A.FormatException$(source, null, null));
     },
-    Error__objectToString(object) {
-      if (object instanceof A.Closure)
-        return object.toString$0(0);
-      return "Instance of '" + A.Primitives_objectTypeName(object) + "'";
-    },
     Error__throw(error, stackTrace) {
       error = A.wrapException(error);
       if (error == null)
@@ -4470,17 +4525,6 @@
       throw error;
       throw A.wrapException("unreachable");
     },
-    DateTime$fromMillisecondsSinceEpoch(millisecondsSinceEpoch, isUtc) {
-      var t1;
-      if (Math.abs(millisecondsSinceEpoch) <= 864e13)
-        t1 = false;
-      else
-        t1 = true;
-      if (t1)
-        A.throwExpression(A.ArgumentError$("DateTime is outside valid range: " + millisecondsSinceEpoch, null));
-      A.checkNotNullable(true, "isUtc", type$.bool);
-      return new A.DateTime(millisecondsSinceEpoch, true);
-    },
     List_List$filled($length, fill, growable, $E) {
       var i,
         result = growable ? J.JSArray_JSArray$growable($length, $E) : J.JSArray_JSArray$fixed($length, $E);
@@ -4499,7 +4543,10 @@
       return J.JSArray_markFixedList(list, $E);
     },
     List_List$of(elements, growable, $E) {
-      var t1 = A.List_List$_of(elements, $E);
+      var t1;
+      if (growable)
+        return A.List_List$_of(elements, $E);
+      t1 = J.JSArray_markFixedList(A.List_List$_of(elements, $E), $E);
       return t1;
     },
     List_List$_of(elements, $E) {
@@ -4570,27 +4617,33 @@
       }
       return string;
     },
-    NoSuchMethodError$(receiver, memberName, positionalArguments, namedArguments) {
-      return new A.NoSuchMethodError(receiver, memberName, positionalArguments, namedArguments);
+    NoSuchMethodError_NoSuchMethodError$withInvocation(receiver, invocation) {
+      return new A.NoSuchMethodError(receiver, invocation.get$memberName(), invocation.get$positionalArguments(), invocation.get$namedArguments());
     },
     Uri_base() {
-      var uri = A.Primitives_currentUri();
-      if (uri != null)
-        return A.Uri_parse(uri);
-      throw A.wrapException(A.UnsupportedError$("'Uri.base' is not supported"));
+      var cachedUri, uri,
+        current = A.Primitives_currentUri();
+      if (current == null)
+        throw A.wrapException(A.UnsupportedError$("'Uri.base' is not supported"));
+      cachedUri = $.Uri__cachedBaseUri;
+      if (cachedUri != null && current === $.Uri__cachedBaseString)
+        return cachedUri;
+      uri = A.Uri_parse(current);
+      $.Uri__cachedBaseUri = uri;
+      $.Uri__cachedBaseString = current;
+      return uri;
     },
     _Uri__uriEncode(canonicalTable, text, encoding, spaceToPlus) {
       var t1, bytes, i, t2, byte, t3,
         _s16_ = "0123456789ABCDEF";
       if (encoding === B.C_Utf8Codec) {
-        t1 = $.$get$_Uri__needsNoEncoding()._nativeRegExp;
-        t1 = t1.test(text);
+        t1 = $.$get$_Uri__needsNoEncoding();
+        t1 = t1._nativeRegExp.test(text);
       } else
         t1 = false;
       if (t1)
         return text;
-      A._instanceType(encoding)._eval$1("Codec.S")._as(text);
-      bytes = encoding.get$encoder().convert$1(text);
+      bytes = B.C_Utf8Encoder.convert$1(text);
       for (t1 = bytes.length, i = 0, t2 = ""; i < t1; ++i) {
         byte = bytes[i];
         if (byte < 128) {
@@ -4635,7 +4688,12 @@
         return J.toString$0$(object);
       if (typeof object == "string")
         return JSON.stringify(object);
-      return A.Error__objectToString(object);
+      return A.Primitives_safeToString(object);
+    },
+    Error_throwWithStackTrace(error, stackTrace) {
+      A.checkNotNullable(error, "error", type$.Object);
+      A.checkNotNullable(stackTrace, "stackTrace", type$.StackTrace);
+      A.Error__throw(error, stackTrace);
     },
     AssertionError$(message) {
       return new A.AssertionError(message);
@@ -4675,9 +4733,8 @@
         throw A.wrapException(A.RangeError$range(value, 0, null, $name, null));
       return value;
     },
-    IndexError$(invalidValue, indexable, $name, message, $length) {
-      var t1 = A._asInt($length == null ? J.get$length$asx(indexable) : $length);
-      return new A.IndexError(t1, true, invalidValue, $name, "Index out of range");
+    IndexError$withLength(invalidValue, $length, indexable, $name) {
+      return new A.IndexError($length, true, invalidValue, $name, "Index out of range");
     },
     UnsupportedError$(message) {
       return new A.UnsupportedError(message);
@@ -4694,8 +4751,126 @@
     FormatException$(message, source, offset) {
       return new A.FormatException(message, source, offset);
     },
+    Iterable_iterableToShortString(iterable, leftDelimiter, rightDelimiter) {
+      var parts, t1;
+      if (A.isToStringVisiting(iterable)) {
+        if (leftDelimiter === "(" && rightDelimiter === ")")
+          return "(...)";
+        return leftDelimiter + "..." + rightDelimiter;
+      }
+      parts = A._setArrayType([], type$.JSArray_String);
+      B.JSArray_methods.add$1($.toStringVisiting, iterable);
+      try {
+        A._iterablePartsToStrings(iterable, parts);
+      } finally {
+        if (0 >= $.toStringVisiting.length)
+          return A.ioore($.toStringVisiting, -1);
+        $.toStringVisiting.pop();
+      }
+      t1 = A.StringBuffer__writeAll(leftDelimiter, type$.Iterable_dynamic._as(parts), ", ") + rightDelimiter;
+      return t1.charCodeAt(0) == 0 ? t1 : t1;
+    },
+    Iterable_iterableToFullString(iterable, leftDelimiter, rightDelimiter) {
+      var buffer, t1;
+      if (A.isToStringVisiting(iterable))
+        return leftDelimiter + "..." + rightDelimiter;
+      buffer = new A.StringBuffer(leftDelimiter);
+      B.JSArray_methods.add$1($.toStringVisiting, iterable);
+      try {
+        t1 = buffer;
+        t1._contents = A.StringBuffer__writeAll(t1._contents, iterable, ", ");
+      } finally {
+        if (0 >= $.toStringVisiting.length)
+          return A.ioore($.toStringVisiting, -1);
+        $.toStringVisiting.pop();
+      }
+      buffer._contents += rightDelimiter;
+      t1 = buffer._contents;
+      return t1.charCodeAt(0) == 0 ? t1 : t1;
+    },
+    _iterablePartsToStrings(iterable, parts) {
+      var next, ultimateString, penultimateString, penultimate, ultimate, ultimate0, elision,
+        it = iterable.get$iterator(iterable),
+        $length = 0, count = 0;
+      while (true) {
+        if (!($length < 80 || count < 3))
+          break;
+        if (!it.moveNext$0())
+          return;
+        next = A.S(it.get$current(it));
+        B.JSArray_methods.add$1(parts, next);
+        $length += next.length + 2;
+        ++count;
+      }
+      if (!it.moveNext$0()) {
+        if (count <= 5)
+          return;
+        if (0 >= parts.length)
+          return A.ioore(parts, -1);
+        ultimateString = parts.pop();
+        if (0 >= parts.length)
+          return A.ioore(parts, -1);
+        penultimateString = parts.pop();
+      } else {
+        penultimate = it.get$current(it);
+        ++count;
+        if (!it.moveNext$0()) {
+          if (count <= 4) {
+            B.JSArray_methods.add$1(parts, A.S(penultimate));
+            return;
+          }
+          ultimateString = A.S(penultimate);
+          if (0 >= parts.length)
+            return A.ioore(parts, -1);
+          penultimateString = parts.pop();
+          $length += ultimateString.length + 2;
+        } else {
+          ultimate = it.get$current(it);
+          ++count;
+          for (; it.moveNext$0(); penultimate = ultimate, ultimate = ultimate0) {
+            ultimate0 = it.get$current(it);
+            ++count;
+            if (count > 100) {
+              while (true) {
+                if (!($length > 75 && count > 3))
+                  break;
+                if (0 >= parts.length)
+                  return A.ioore(parts, -1);
+                $length -= parts.pop().length + 2;
+                --count;
+              }
+              B.JSArray_methods.add$1(parts, "...");
+              return;
+            }
+          }
+          penultimateString = A.S(penultimate);
+          ultimateString = A.S(ultimate);
+          $length += ultimateString.length + penultimateString.length + 4;
+        }
+      }
+      if (count > parts.length + 2) {
+        $length += 5;
+        elision = "...";
+      } else
+        elision = null;
+      while (true) {
+        if (!($length > 80 && parts.length > 3))
+          break;
+        if (0 >= parts.length)
+          return A.ioore(parts, -1);
+        $length -= parts.pop().length + 2;
+        if (elision == null) {
+          $length += 5;
+          elision = "...";
+        }
+      }
+      if (elision != null)
+        B.JSArray_methods.add$1(parts, elision);
+      B.JSArray_methods.add$1(parts, penultimateString);
+      B.JSArray_methods.add$1(parts, ultimateString);
+    },
     Object_hash(object1, object2, object3, object4) {
-      var t1, t2;
+      var t1;
       if (B.C_SentinelValue === object3) {
         t1 = J.get$hashCode$(object1);
         object2 = J.get$hashCode$(object2);
@@ -4711,8 +4886,8 @@
       object2 = J.get$hashCode$(object2);
       object3 = J.get$hashCode$(object3);
       object4 = J.get$hashCode$(object4);
-      t2 = $.$get$_hashSeed();
-      return A.SystemHash_finish(A.SystemHash_combine(A.SystemHash_combine(A.SystemHash_combine(A.SystemHash_combine(t2, t1), object2), object3), object4));
+      object4 = A.SystemHash_finish(A.SystemHash_combine(A.SystemHash_combine(A.SystemHash_combine(A.SystemHash_combine($.$get$_hashSeed(), t1), object2), object3), object4));
+      return object4;
     },
     Uri_Uri$dataFromString($content) {
       var t1, _null = null,
@@ -4721,7 +4896,7 @@
       A.UriData__writeUri(_null, _null, _null, buffer, indices);
       B.JSArray_methods.add$1(indices, buffer._contents.length);
       buffer._contents += ",";
-      A.UriData__uriEncodeBytes(B.List_CVk, B.C_AsciiCodec.encode$1($content), buffer);
+      A.UriData__uriEncodeBytes(B.List_oFp, B.C_AsciiCodec.encode$1($content), buffer);
       t1 = buffer._contents;
       return new A.UriData(t1.charCodeAt(0) == 0 ? t1 : t1, indices, _null).get$uri();
     },
@@ -4729,7 +4904,9 @@
       var delta, indices, schemeEnd, hostStart, portStart, pathStart, queryStart, fragmentStart, isSimple, scheme, t1, t2, schemeAuth, queryStart0, pathStart0, userInfoStart, userInfo, host, portNumber, port, path, query, _null = null,
         end = uri.length;
       if (end >= 5) {
-        delta = ((B.JSString_methods._codeUnitAt$1(uri, 4) ^ 58) * 3 | B.JSString_methods._codeUnitAt$1(uri, 0) ^ 100 | B.JSString_methods._codeUnitAt$1(uri, 1) ^ 97 | B.JSString_methods._codeUnitAt$1(uri, 2) ^ 116 | B.JSString_methods._codeUnitAt$1(uri, 3) ^ 97) >>> 0;
+        if (4 >= end)
+          return A.ioore(uri, 4);
+        delta = ((uri.charCodeAt(4) ^ 58) * 3 | uri.charCodeAt(0) ^ 100 | uri.charCodeAt(1) ^ 97 | uri.charCodeAt(2) ^ 116 | uri.charCodeAt(3) ^ 97) >>> 0;
         if (delta === 0)
           return A.UriData__parse(end < end ? B.JSString_methods.substring$2(uri, 0, end) : uri, 5, _null).get$uri();
         else if (delta === 32)
@@ -4774,66 +4951,78 @@
             scheme = _null;
             isSimple = false;
           } else {
-            if (!(queryStart < end && queryStart === pathStart + 2 && B.JSString_methods.startsWith$2(uri, "..", pathStart)))
-              t2 = queryStart > pathStart + 2 && B.JSString_methods.startsWith$2(uri, "/..", queryStart - 3);
+            if (!B.JSString_methods.startsWith$2(uri, "\\", pathStart))
+              if (hostStart > 0)
+                t2 = B.JSString_methods.startsWith$2(uri, "\\", hostStart - 1) || B.JSString_methods.startsWith$2(uri, "\\", hostStart - 2);
+              else
+                t2 = false;
             else
               t2 = true;
             if (t2) {
               scheme = _null;
               isSimple = false;
             } else {
-              if (schemeEnd === 4)
-                if (B.JSString_methods.startsWith$2(uri, "file", 0)) {
-                  if (hostStart <= 0) {
-                    if (!B.JSString_methods.startsWith$2(uri, "/", pathStart)) {
-                      schemeAuth = "file:///";
-                      delta = 3;
-                    } else {
-                      schemeAuth = "file://";
-                      delta = 2;
+              if (!(queryStart < end && queryStart === pathStart + 2 && B.JSString_methods.startsWith$2(uri, "..", pathStart)))
+                t2 = queryStart > pathStart + 2 && B.JSString_methods.startsWith$2(uri, "/..", queryStart - 3);
+              else
+                t2 = true;
+              if (t2) {
+                scheme = _null;
+                isSimple = false;
+              } else {
+                if (schemeEnd === 4)
+                  if (B.JSString_methods.startsWith$2(uri, "file", 0)) {
+                    if (hostStart <= 0) {
+                      if (!B.JSString_methods.startsWith$2(uri, "/", pathStart)) {
+                        schemeAuth = "file:///";
+                        delta = 3;
+                      } else {
+                        schemeAuth = "file://";
+                        delta = 2;
+                      }
+                      uri = schemeAuth + B.JSString_methods.substring$2(uri, pathStart, end);
+                      schemeEnd -= 0;
+                      t1 = delta - 0;
+                      queryStart += t1;
+                      fragmentStart += t1;
+                      end = uri.length;
+                      hostStart = 7;
+                      portStart = 7;
+                      pathStart = 7;
+                    } else if (pathStart === queryStart) {
+                      ++fragmentStart;
+                      queryStart0 = queryStart + 1;
+                      uri = B.JSString_methods.replaceRange$3(uri, pathStart, queryStart, "/");
+                      ++end;
+                      queryStart = queryStart0;
                     }
-                    uri = schemeAuth + B.JSString_methods.substring$2(uri, pathStart, end);
-                    schemeEnd -= 0;
-                    t1 = delta - 0;
-                    queryStart += t1;
-                    fragmentStart += t1;
-                    end = uri.length;
-                    hostStart = 7;
-                    portStart = 7;
-                    pathStart = 7;
-                  } else if (pathStart === queryStart) {
-                    ++fragmentStart;
-                    queryStart0 = queryStart + 1;
-                    uri = B.JSString_methods.replaceRange$3(uri, pathStart, queryStart, "/");
-                    ++end;
-                    queryStart = queryStart0;
-                  }
-                  scheme = "file";
-                } else if (B.JSString_methods.startsWith$2(uri, "http", 0)) {
-                  if (t1 && portStart + 3 === pathStart && B.JSString_methods.startsWith$2(uri, "80", portStart + 1)) {
-                    fragmentStart -= 3;
-                    pathStart0 = pathStart - 3;
-                    queryStart -= 3;
+                    scheme = "file";
+                  } else if (B.JSString_methods.startsWith$2(uri, "http", 0)) {
+                    if (t1 && portStart + 3 === pathStart && B.JSString_methods.startsWith$2(uri, "80", portStart + 1)) {
+                      fragmentStart -= 3;
+                      pathStart0 = pathStart - 3;
+                      queryStart -= 3;
+                      uri = B.JSString_methods.replaceRange$3(uri, portStart, pathStart, "");
+                      end -= 3;
+                      pathStart = pathStart0;
+                    }
+                    scheme = "http";
+                  } else
+                    scheme = _null;
+                else if (schemeEnd === 5 && B.JSString_methods.startsWith$2(uri, "https", 0)) {
+                  if (t1 && portStart + 4 === pathStart && B.JSString_methods.startsWith$2(uri, "443", portStart + 1)) {
+                    fragmentStart -= 4;
+                    pathStart0 = pathStart - 4;
+                    queryStart -= 4;
                     uri = B.JSString_methods.replaceRange$3(uri, portStart, pathStart, "");
                     end -= 3;
                     pathStart = pathStart0;
                   }
-                  scheme = "http";
+                  scheme = "https";
                 } else
                   scheme = _null;
-              else if (schemeEnd === 5 && B.JSString_methods.startsWith$2(uri, "https", 0)) {
-                if (t1 && portStart + 4 === pathStart && B.JSString_methods.startsWith$2(uri, "443", portStart + 1)) {
-                  fragmentStart -= 4;
-                  pathStart0 = pathStart - 4;
-                  queryStart -= 4;
-                  uri = B.JSString_methods.replaceRange$3(uri, portStart, pathStart, "");
-                  end -= 3;
-                  pathStart = pathStart0;
-                }
-                scheme = "https";
-              } else
-                scheme = _null;
-              isSimple = true;
+                isSimple = true;
+              }
             }
           }
         }
@@ -4887,13 +5076,15 @@
       return B.JSArray_methods.fold$1$2(A._setArrayType(query.split("&"), type$.JSArray_String), A.LinkedHashMap_LinkedHashMap$_empty(t1, t1), new A.Uri_splitQueryString_closure(B.C_Utf8Codec), type$.Map_String_String);
     },
     Uri__parseIPv4Address(host, start, end) {
-      var i, partStart, partIndex, char, part, partIndex0,
+      var t1, i, partStart, partIndex, char, part, partIndex0,
         _s43_ = "IPv4 address should contain exactly 4 parts",
         _s37_ = "each part must be in the range 0..255",
         error = new A.Uri__parseIPv4Address_error(host),
         result = new Uint8Array(4);
-      for (i = start, partStart = i, partIndex = 0; i < end; ++i) {
-        char = B.JSString_methods.codeUnitAt$1(host, i);
+      for (t1 = host.length, i = start, partStart = i, partIndex = 0; i < end; ++i) {
+        if (!(i >= 0 && i < t1))
+          return A.ioore(host, i);
+        char = host.charCodeAt(i);
         if (char !== 46) {
           if ((char ^ 48) > 9)
             error.call$2("invalid character", i);
@@ -4922,18 +5113,23 @@
       return result;
     },
     Uri_parseIPv6Address(host, start, end) {
-      var parts, i, partStart, wildcardSeen, seenDot, char, atEnd, t1, last, bytes, wildCardLength, index, value, j, t2, _null = null,
+      var parts, i, partStart, wildcardSeen, seenDot, char, atEnd, last, bytes, wildCardLength, index, value, j, t2, _null = null,
         error = new A.Uri_parseIPv6Address_error(host),
-        parseHex = new A.Uri_parseIPv6Address_parseHex(error, host);
-      if (host.length < 2)
+        parseHex = new A.Uri_parseIPv6Address_parseHex(error, host),
+        t1 = host.length;
+      if (t1 < 2)
         error.call$2("address is too short", _null);
       parts = A._setArrayType([], type$.JSArray_int);
       for (i = start, partStart = i, wildcardSeen = false, seenDot = false; i < end; ++i) {
-        char = B.JSString_methods.codeUnitAt$1(host, i);
+        if (!(i >= 0 && i < t1))
+          return A.ioore(host, i);
+        char = host.charCodeAt(i);
         if (char === 58) {
           if (i === start) {
             ++i;
-            if (B.JSString_methods.codeUnitAt$1(host, i) !== 58)
+            if (!(i < t1))
+              return A.ioore(host, i);
+            if (host.charCodeAt(i) !== 58)
               error.call$2("invalid start colon.", i);
             partStart = i;
           }
@@ -5037,30 +5233,24 @@
       return windows ? A._Uri__makeWindowsFileUrl(path, false) : A._Uri__makeFileUri(path, false);
     },
     _Uri__checkNonWindowsPathReservedCharacters(segments, argumentError) {
-      var t1, _i, segment, t2, t3;
+      var t1, _i, segment;
       for (t1 = segments.length, _i = 0; _i < t1; ++_i) {
         segment = segments[_i];
-        t2 = J.getInterceptor$asx(segment);
-        t3 = t2.get$length(segment);
-        if (0 > t3)
-          A.throwExpression(A.RangeError$range(0, 0, t2.get$length(segment), null, null));
-        if (A.stringContainsUnchecked(segment, "/", 0)) {
+        if (J.contains$1$asx(segment, "/")) {
           t1 = A.UnsupportedError$("Illegal path character " + A.S(segment));
           throw A.wrapException(t1);
         }
       }
     },
     _Uri__checkWindowsPathReservedCharacters(segments, argumentError, firstSegment) {
-      var t1, t2, t3, t4, t5, _null = null;
-      for (t1 = A.SubListIterable$(segments, firstSegment, _null, A._arrayInstanceType(segments)._precomputed1), t2 = t1.$ti, t1 = new A.ListIterator(t1, t1.get$length(t1), t2._eval$1("ListIterator<ListIterable.E>")), t2 = t2._eval$1("ListIterable.E"); t1.moveNext$0();) {
+      var t1, t2, t3;
+      for (t1 = A.SubListIterable$(segments, firstSegment, null, A._arrayInstanceType(segments)._precomputed1), t2 = t1.$ti, t1 = new A.ListIterator(t1, t1.get$length(t1), t2._eval$1("ListIterator<ListIterable.E>")), t2 = t2._eval$1("ListIterable.E"); t1.moveNext$0();) {
         t3 = t1.__internal$_current;
         if (t3 == null)
           t3 = t2._as(t3);
-        t4 = A.RegExp_RegExp('["*/:<>?\\\\|]', false);
-        t5 = t3.length;
-        if (A.stringContainsUnchecked(t3, t4, 0))
+        if (B.JSString_methods.contains$1(t3, A.RegExp_RegExp('["*/:<>?\\\\|]', false)))
           if (argumentError)
-            throw A.wrapException(A.ArgumentError$("Illegal character in path", _null));
+            throw A.wrapException(A.ArgumentError$("Illegal character in path", null));
           else
             throw A.wrapException(A.UnsupportedError$("Illegal character in path: " + t3));
       }
@@ -5094,16 +5284,36 @@
           path = B.JSString_methods.replaceRange$3(path, 0, 7, _s1_);
         else {
           path = B.JSString_methods.substring$1(path, 4);
-          if (path.length < 3 || B.JSString_methods._codeUnitAt$1(path, 1) !== 58 || B.JSString_methods._codeUnitAt$1(path, 2) !== 92)
-            throw A.wrapException(A.ArgumentError$("Windows paths with \\\\?\\ prefix must be absolute", _null));
+          t1 = path.length;
+          if (t1 >= 3) {
+            if (1 >= t1)
+              return A.ioore(path, 1);
+            if (path.charCodeAt(1) === 58) {
+              if (2 >= t1)
+                return A.ioore(path, 2);
+              t1 = path.charCodeAt(2) !== 92;
+            } else
+              t1 = true;
+          } else
+            t1 = true;
+          if (t1)
+            throw A.wrapException(A.ArgumentError$value(path, "path", "Windows paths with \\\\?\\ prefix must be absolute"));
         }
       else
         path = A.stringReplaceAllUnchecked(path, "/", _s1_);
       t1 = path.length;
-      if (t1 > 1 && B.JSString_methods._codeUnitAt$1(path, 1) === 58) {
-        A._Uri__checkWindowsDriveLetter(B.JSString_methods._codeUnitAt$1(path, 0), true);
-        if (t1 === 2 || B.JSString_methods._codeUnitAt$1(path, 2) !== 92)
-          throw A.wrapException(A.ArgumentError$("Windows paths with drive letter must be absolute", _null));
+      if (t1 > 1 && path.charCodeAt(1) === 58) {
+        if (0 >= t1)
+          return A.ioore(path, 0);
+        A._Uri__checkWindowsDriveLetter(path.charCodeAt(0), true);
+        if (t1 !== 2) {
+          if (2 >= t1)
+            return A.ioore(path, 2);
+          t1 = path.charCodeAt(2) !== 92;
+        } else
+          t1 = true;
+        if (t1)
+          throw A.wrapException(A.ArgumentError$value(path, "path", "Windows paths with drive letter must be absolute"));
         pathSegments = A._setArrayType(path.split(_s1_), type$.JSArray_String);
         A._Uri__checkWindowsPathReservedCharacters(pathSegments, true, 1);
         return A._Uri__Uri(_null, _null, pathSegments, _s4_);
@@ -5138,22 +5348,29 @@
         return null;
       if (start === end)
         return "";
-      if (B.JSString_methods.codeUnitAt$1(host, start) === 91) {
-        t1 = end - 1;
-        if (B.JSString_methods.codeUnitAt$1(host, t1) !== 93)
+      t1 = host.length;
+      if (!(start >= 0 && start < t1))
+        return A.ioore(host, start);
+      if (host.charCodeAt(start) === 91) {
+        t2 = end - 1;
+        if (!(t2 >= 0 && t2 < t1))
+          return A.ioore(host, t2);
+        if (host.charCodeAt(t2) !== 93)
           A._Uri__fail(host, start, "Missing end `]` to match `[` in host");
-        t2 = start + 1;
-        index = A._Uri__checkZoneID(host, t2, t1);
-        if (index < t1) {
+        t1 = start + 1;
+        index = A._Uri__checkZoneID(host, t1, t2);
+        if (index < t2) {
           zoneIDstart = index + 1;
-          zoneID = A._Uri__normalizeZoneID(host, B.JSString_methods.startsWith$2(host, "25", zoneIDstart) ? index + 3 : zoneIDstart, t1, "%25");
+          zoneID = A._Uri__normalizeZoneID(host, B.JSString_methods.startsWith$2(host, "25", zoneIDstart) ? index + 3 : zoneIDstart, t2, "%25");
         } else
           zoneID = "";
-        A.Uri_parseIPv6Address(host, t2, index);
+        A.Uri_parseIPv6Address(host, t1, index);
         return B.JSString_methods.substring$2(host, start, index).toLowerCase() + zoneID + "]";
       }
-      for (i = start; i < end; ++i)
-        if (B.JSString_methods.codeUnitAt$1(host, i) === 58) {
+      for (i = start; i < end; ++i) {
+        if (!(i < t1))
+          return A.ioore(host, i);
+        if (host.charCodeAt(i) === 58) {
           index = B.JSString_methods.indexOf$2(host, "%", start);
           index = index >= start && index < end ? index : end;
           if (index < end) {
@@ -5164,6 +5381,7 @@
           A.Uri_parseIPv6Address(host, start, index);
           return "[" + B.JSString_methods.substring$2(host, start, index) + zoneID + "]";
         }
+      }
       return A._Uri__normalizeRegName(host, start, end);
     },
     _Uri__checkZoneID(host, start, end) {
@@ -5171,37 +5389,39 @@
       return index >= start && index < end ? index : end;
     },
     _Uri__normalizeZoneID(host, start, end, prefix) {
-      var index, sectionStart, isNormalized, char, replacement, t1, t2, tail, sourceLength, slice,
+      var t1, index, sectionStart, isNormalized, char, replacement, t2, t3, tail, sourceLength, slice,
         buffer = prefix !== "" ? new A.StringBuffer(prefix) : null;
-      for (index = start, sectionStart = index, isNormalized = true; index < end;) {
-        char = B.JSString_methods.codeUnitAt$1(host, index);
+      for (t1 = host.length, index = start, sectionStart = index, isNormalized = true; index < end;) {
+        if (!(index >= 0 && index < t1))
+          return A.ioore(host, index);
+        char = host.charCodeAt(index);
         if (char === 37) {
           replacement = A._Uri__normalizeEscape(host, index, true);
-          t1 = replacement == null;
-          if (t1 && isNormalized) {
+          t2 = replacement == null;
+          if (t2 && isNormalized) {
             index += 3;
             continue;
           }
           if (buffer == null)
             buffer = new A.StringBuffer("");
-          t2 = buffer._contents += B.JSString_methods.substring$2(host, sectionStart, index);
-          if (t1)
+          t3 = buffer._contents += B.JSString_methods.substring$2(host, sectionStart, index);
+          if (t2)
             replacement = B.JSString_methods.substring$2(host, index, index + 3);
           else if (replacement === "%")
             A._Uri__fail(host, index, "ZoneID should not contain % anymore");
-          buffer._contents = t2 + replacement;
+          buffer._contents = t3 + replacement;
           index += 3;
           sectionStart = index;
           isNormalized = true;
         } else {
           if (char < 127) {
-            t1 = char >>> 4;
-            if (!(t1 < 8))
-              return A.ioore(B.List_nxB, t1);
-            t1 = (B.List_nxB[t1] & 1 << (char & 15)) !== 0;
+            t2 = char >>> 4;
+            if (!(t2 < 8))
+              return A.ioore(B.List_M1A, t2);
+            t2 = (B.List_M1A[t2] & 1 << (char & 15)) !== 0;
           } else
-            t1 = false;
-          if (t1) {
+            t2 = false;
+          if (t2) {
             if (isNormalized && 65 <= char && 90 >= char) {
               if (buffer == null)
                 buffer = new A.StringBuffer("");
@@ -5214,7 +5434,10 @@
             ++index;
           } else {
             if ((char & 64512) === 55296 && index + 1 < end) {
-              tail = B.JSString_methods.codeUnitAt$1(host, index + 1);
+              t2 = index + 1;
+              if (!(t2 < t1))
+                return A.ioore(host, t2);
+              tail = host.charCodeAt(t2);
               if ((tail & 64512) === 56320) {
                 char = (char & 1023) << 10 | tail & 1023 | 65536;
                 sourceLength = 2;
@@ -5225,11 +5448,11 @@
             slice = B.JSString_methods.substring$2(host, sectionStart, index);
             if (buffer == null) {
               buffer = new A.StringBuffer("");
-              t1 = buffer;
+              t2 = buffer;
             } else
-              t1 = buffer;
-            t1._contents += slice;
-            t1._contents += A._Uri__escapeChar(char);
+              t2 = buffer;
+            t2._contents += slice;
+            t2._contents += A._Uri__escapeChar(char);
             index += sourceLength;
             sectionStart = index;
           }
@@ -5243,21 +5466,23 @@
       return t1.charCodeAt(0) == 0 ? t1 : t1;
     },
     _Uri__normalizeRegName(host, start, end) {
-      var index, sectionStart, buffer, isNormalized, char, replacement, t1, slice, t2, sourceLength, tail;
-      for (index = start, sectionStart = index, buffer = null, isNormalized = true; index < end;) {
-        char = B.JSString_methods.codeUnitAt$1(host, index);
+      var t1, index, sectionStart, buffer, isNormalized, char, replacement, t2, slice, t3, sourceLength, tail;
+      for (t1 = host.length, index = start, sectionStart = index, buffer = null, isNormalized = true; index < end;) {
+        if (!(index >= 0 && index < t1))
+          return A.ioore(host, index);
+        char = host.charCodeAt(index);
         if (char === 37) {
           replacement = A._Uri__normalizeEscape(host, index, true);
-          t1 = replacement == null;
-          if (t1 && isNormalized) {
+          t2 = replacement == null;
+          if (t2 && isNormalized) {
             index += 3;
             continue;
           }
           if (buffer == null)
             buffer = new A.StringBuffer("");
           slice = B.JSString_methods.substring$2(host, sectionStart, index);
-          t2 = buffer._contents += !isNormalized ? slice.toLowerCase() : slice;
-          if (t1) {
+          t3 = buffer._contents += !isNormalized ? slice.toLowerCase() : slice;
+          if (t2) {
             replacement = B.JSString_methods.substring$2(host, index, index + 3);
             sourceLength = 3;
           } else if (replacement === "%") {
@@ -5265,19 +5490,19 @@
             sourceLength = 1;
           } else
             sourceLength = 3;
-          buffer._contents = t2 + replacement;
+          buffer._contents = t3 + replacement;
           index += sourceLength;
           sectionStart = index;
           isNormalized = true;
         } else {
           if (char < 127) {
-            t1 = char >>> 4;
-            if (!(t1 < 8))
-              return A.ioore(B.List_qNA, t1);
-            t1 = (B.List_qNA[t1] & 1 << (char & 15)) !== 0;
+            t2 = char >>> 4;
+            if (!(t2 < 8))
+              return A.ioore(B.List_ejq, t2);
+            t2 = (B.List_ejq[t2] & 1 << (char & 15)) !== 0;
           } else
-            t1 = false;
-          if (t1) {
+            t2 = false;
+          if (t2) {
             if (isNormalized && 65 <= char && 90 >= char) {
               if (buffer == null)
                 buffer = new A.StringBuffer("");
@@ -5290,17 +5515,20 @@
             ++index;
           } else {
             if (char <= 93) {
-              t1 = char >>> 4;
-              if (!(t1 < 8))
-                return A.ioore(B.List_2Vk, t1);
-              t1 = (B.List_2Vk[t1] & 1 << (char & 15)) !== 0;
+              t2 = char >>> 4;
+              if (!(t2 < 8))
+                return A.ioore(B.List_YmH, t2);
+              t2 = (B.List_YmH[t2] & 1 << (char & 15)) !== 0;
             } else
-              t1 = false;
-            if (t1)
+              t2 = false;
+            if (t2)
               A._Uri__fail(host, index, "Invalid character");
             else {
               if ((char & 64512) === 55296 && index + 1 < end) {
-                tail = B.JSString_methods.codeUnitAt$1(host, index + 1);
+                t2 = index + 1;
+                if (!(t2 < t1))
+                  return A.ioore(host, t2);
+                tail = host.charCodeAt(t2);
                 if ((tail & 64512) === 56320) {
                   char = (char & 1023) << 10 | tail & 1023 | 65536;
                   sourceLength = 2;
@@ -5313,11 +5541,11 @@
                 slice = slice.toLowerCase();
               if (buffer == null) {
                 buffer = new A.StringBuffer("");
-                t1 = buffer;
+                t2 = buffer;
               } else
-                t1 = buffer;
-              t1._contents += slice;
-              t1._contents += A._Uri__escapeChar(char);
+                t2 = buffer;
+              t2._contents += slice;
+              t2._contents += A._Uri__escapeChar(char);
               index += sourceLength;
               sectionStart = index;
             }
@@ -5334,21 +5562,26 @@
       return t1.charCodeAt(0) == 0 ? t1 : t1;
     },
     _Uri__makeScheme(scheme, start, end) {
-      var i, containsUpperCase, codeUnit, t1;
+      var t1, i, containsUpperCase, codeUnit, t2;
       if (start === end)
         return "";
-      if (!A._Uri__isAlphabeticCharacter(B.JSString_methods._codeUnitAt$1(scheme, start)))
+      t1 = scheme.length;
+      if (!(start < t1))
+        return A.ioore(scheme, start);
+      if (!A._Uri__isAlphabeticCharacter(scheme.charCodeAt(start)))
         A._Uri__fail(scheme, start, "Scheme not starting with alphabetic character");
       for (i = start, containsUpperCase = false; i < end; ++i) {
-        codeUnit = B.JSString_methods._codeUnitAt$1(scheme, i);
+        if (!(i < t1))
+          return A.ioore(scheme, i);
+        codeUnit = scheme.charCodeAt(i);
         if (codeUnit < 128) {
-          t1 = codeUnit >>> 4;
-          if (!(t1 < 8))
-            return A.ioore(B.List_JYB, t1);
-          t1 = (B.List_JYB[t1] & 1 << (codeUnit & 15)) !== 0;
+          t2 = codeUnit >>> 4;
+          if (!(t2 < 8))
+            return A.ioore(B.List_MMm, t2);
+          t2 = (B.List_MMm[t2] & 1 << (codeUnit & 15)) !== 0;
         } else
-          t1 = false;
-        if (!t1)
+          t2 = false;
+        if (!t2)
           A._Uri__fail(scheme, i, "Illegal scheme character");
         if (65 <= codeUnit && codeUnit <= 90)
           containsUpperCase = true;
@@ -5370,7 +5603,7 @@
     _Uri__makeUserInfo(userInfo, start, end) {
       if (userInfo == null)
         return "";
-      return A._Uri__normalizeOrSubstring(userInfo, start, end, B.List_gRj, false);
+      return A._Uri__normalizeOrSubstring(userInfo, start, end, B.List_OL3, false, false);
     },
     _Uri__makePath(path, start, end, pathSegments, scheme, hasAuthority) {
       var t1, result,
@@ -5384,7 +5617,7 @@
       } else if (pathSegments != null)
         throw A.wrapException(A.ArgumentError$("Both path and pathSegments specified", null));
       else
-        result = A._Uri__normalizeOrSubstring(path, start, end, B.List_qg4, true);
+        result = A._Uri__normalizeOrSubstring(path, start, end, B.List_XRg, true, true);
       if (result.length === 0) {
         if (isFile)
           return "/";
@@ -5394,27 +5627,33 @@
     },
     _Uri__normalizePath(path, scheme, hasAuthority) {
       var t1 = scheme.length === 0;
-      if (t1 && !hasAuthority && !B.JSString_methods.startsWith$1(path, "/"))
+      if (t1 && !hasAuthority && !B.JSString_methods.startsWith$1(path, "/") && !B.JSString_methods.startsWith$1(path, "\\"))
         return A._Uri__normalizeRelativePath(path, !t1 || hasAuthority);
       return A._Uri__removeDotSegments(path);
     },
     _Uri__makeQuery(query, start, end, queryParameters) {
       if (query != null)
-        return A._Uri__normalizeOrSubstring(query, start, end, B.List_CVk, true);
+        return A._Uri__normalizeOrSubstring(query, start, end, B.List_oFp, true, false);
       return null;
     },
     _Uri__makeFragment(fragment, start, end) {
       if (fragment == null)
         return null;
-      return A._Uri__normalizeOrSubstring(fragment, start, end, B.List_CVk, true);
+      return A._Uri__normalizeOrSubstring(fragment, start, end, B.List_oFp, true, false);
     },
     _Uri__normalizeEscape(source, index, lowerCase) {
-      var firstDigit, secondDigit, firstDigitValue, secondDigitValue, value,
-        t1 = index + 2;
-      if (t1 >= source.length)
+      var t3, firstDigit, secondDigit, firstDigitValue, secondDigitValue, value,
+        t1 = index + 2,
+        t2 = source.length;
+      if (t1 >= t2)
         return "%";
-      firstDigit = B.JSString_methods.codeUnitAt$1(source, index + 1);
-      secondDigit = B.JSString_methods.codeUnitAt$1(source, t1);
+      t3 = index + 1;
+      if (!(t3 >= 0 && t3 < t2))
+        return A.ioore(source, t3);
+      firstDigit = source.charCodeAt(t3);
+      if (!(t1 >= 0))
+        return A.ioore(source, t1);
+      secondDigit = source.charCodeAt(t1);
       firstDigitValue = A.hexDigitValue(firstDigit);
       secondDigitValue = A.hexDigitValue(secondDigit);
       if (firstDigitValue < 0 || secondDigitValue < 0)
@@ -5423,8 +5662,8 @@
       if (value < 127) {
         t1 = B.JSInt_methods._shrOtherPositive$1(value, 4);
         if (!(t1 < 8))
-          return A.ioore(B.List_nxB, t1);
-        t1 = (B.List_nxB[t1] & 1 << (value & 15)) !== 0;
+          return A.ioore(B.List_M1A, t1);
+        t1 = (B.List_M1A[t1] & 1 << (value & 15)) !== 0;
       } else
         t1 = false;
       if (t1)
@@ -5434,13 +5673,16 @@
       return null;
     },
     _Uri__escapeChar(char) {
-      var codeUnits, flag, encodedBytes, t1, index, byte, t2, t3,
+      var codeUnits, t1, flag, encodedBytes, index, byte, t2, t3,
         _s16_ = "0123456789ABCDEF";
       if (char < 128) {
         codeUnits = new Uint8Array(3);
         codeUnits[0] = 37;
-        codeUnits[1] = B.JSString_methods._codeUnitAt$1(_s16_, char >>> 4);
-        codeUnits[2] = B.JSString_methods._codeUnitAt$1(_s16_, char & 15);
+        t1 = char >>> 4;
+        if (!(t1 < 16))
+          return A.ioore(_s16_, t1);
+        codeUnits[1] = _s16_.charCodeAt(t1);
+        codeUnits[2] = _s16_.charCodeAt(char & 15);
       } else {
         if (char > 2047)
           if (char > 65535) {
@@ -5462,36 +5704,39 @@
             return A.ioore(codeUnits, index);
           codeUnits[index] = 37;
           t2 = index + 1;
-          t3 = B.JSString_methods._codeUnitAt$1(_s16_, byte >>> 4);
+          t3 = byte >>> 4;
+          if (!(t3 < 16))
+            return A.ioore(_s16_, t3);
           if (!(t2 < t1))
             return A.ioore(codeUnits, t2);
-          codeUnits[t2] = t3;
+          codeUnits[t2] = _s16_.charCodeAt(t3);
           t3 = index + 2;
-          t2 = B.JSString_methods._codeUnitAt$1(_s16_, byte & 15);
           if (!(t3 < t1))
             return A.ioore(codeUnits, t3);
-          codeUnits[t3] = t2;
+          codeUnits[t3] = _s16_.charCodeAt(byte & 15);
           index += 3;
         }
       }
       return A.String_String$fromCharCodes(codeUnits, 0, null);
     },
-    _Uri__normalizeOrSubstring(component, start, end, charTable, escapeDelimiters) {
-      var t1 = A._Uri__normalize(component, start, end, charTable, escapeDelimiters);
+    _Uri__normalizeOrSubstring(component, start, end, charTable, escapeDelimiters, replaceBackslash) {
+      var t1 = A._Uri__normalize(component, start, end, charTable, escapeDelimiters, replaceBackslash);
       return t1 == null ? B.JSString_methods.substring$2(component, start, end) : t1;
     },
-    _Uri__normalize(component, start, end, charTable, escapeDelimiters) {
-      var t1, index, sectionStart, buffer, char, t2, replacement, sourceLength, tail, t3, _null = null;
-      for (t1 = !escapeDelimiters, index = start, sectionStart = index, buffer = _null; index < end;) {
-        char = B.JSString_methods.codeUnitAt$1(component, index);
+    _Uri__normalize(component, start, end, charTable, escapeDelimiters, replaceBackslash) {
+      var t1, t2, index, sectionStart, buffer, char, t3, replacement, sourceLength, tail, t4, _null = null;
+      for (t1 = !escapeDelimiters, t2 = component.length, index = start, sectionStart = index, buffer = _null; index < end;) {
+        if (!(index >= 0 && index < t2))
+          return A.ioore(component, index);
+        char = component.charCodeAt(index);
         if (char < 127) {
-          t2 = char >>> 4;
-          if (!(t2 < 8))
-            return A.ioore(charTable, t2);
-          t2 = (charTable[t2] & 1 << (char & 15)) !== 0;
+          t3 = char >>> 4;
+          if (!(t3 < 8))
+            return A.ioore(charTable, t3);
+          t3 = (charTable[t3] & 1 << (char & 15)) !== 0;
         } else
-          t2 = false;
-        if (t2)
+          t3 = false;
+        if (t3)
           ++index;
         else {
           if (char === 37) {
@@ -5505,26 +5750,31 @@
               sourceLength = 1;
             } else
               sourceLength = 3;
+          } else if (char === 92 && replaceBackslash) {
+            replacement = "/";
+            sourceLength = 1;
           } else {
             if (t1)
               if (char <= 93) {
-                t2 = char >>> 4;
-                if (!(t2 < 8))
-                  return A.ioore(B.List_2Vk, t2);
-                t2 = (B.List_2Vk[t2] & 1 << (char & 15)) !== 0;
+                t3 = char >>> 4;
+                if (!(t3 < 8))
+                  return A.ioore(B.List_YmH, t3);
+                t3 = (B.List_YmH[t3] & 1 << (char & 15)) !== 0;
               } else
-                t2 = false;
+                t3 = false;
             else
-              t2 = false;
-            if (t2) {
+              t3 = false;
+            if (t3) {
               A._Uri__fail(component, index, "Invalid character");
               sourceLength = _null;
               replacement = sourceLength;
             } else {
               if ((char & 64512) === 55296) {
-                t2 = index + 1;
-                if (t2 < end) {
-                  tail = B.JSString_methods.codeUnitAt$1(component, t2);
+                t3 = index + 1;
+                if (t3 < end) {
+                  if (!(t3 < t2))
+                    return A.ioore(component, t3);
+                  tail = component.charCodeAt(t3);
                   if ((tail & 64512) === 56320) {
                     char = (char & 1023) << 10 | tail & 1023 | 65536;
                     sourceLength = 2;
@@ -5539,11 +5789,11 @@
           }
           if (buffer == null) {
             buffer = new A.StringBuffer("");
-            t2 = buffer;
+            t3 = buffer;
           } else
-            t2 = buffer;
-          t3 = t2._contents += B.JSString_methods.substring$2(component, sectionStart, index);
-          t2._contents = t3 + A.S(replacement);
+            t3 = buffer;
+          t4 = t3._contents += B.JSString_methods.substring$2(component, sectionStart, index);
+          t3._contents = t4 + A.S(replacement);
           if (typeof sourceLength !== "number")
             return A.iae(sourceLength);
           index += sourceLength;
@@ -5638,16 +5888,16 @@
     _Uri__escapeScheme(path) {
       var i, char, t2,
         t1 = path.length;
-      if (t1 >= 2 && A._Uri__isAlphabeticCharacter(B.JSString_methods._codeUnitAt$1(path, 0)))
+      if (t1 >= 2 && A._Uri__isAlphabeticCharacter(path.charCodeAt(0)))
         for (i = 1; i < t1; ++i) {
-          char = B.JSString_methods._codeUnitAt$1(path, i);
+          char = path.charCodeAt(i);
           if (char === 58)
             return B.JSString_methods.substring$2(path, 0, i) + "%3A" + B.JSString_methods.substring$1(path, i + 1);
           if (char <= 127) {
             t2 = char >>> 4;
             if (!(t2 < 8))
-              return A.ioore(B.List_JYB, t2);
-            t2 = (B.List_JYB[t2] & 1 << (char & 15)) === 0;
+              return A.ioore(B.List_MMm, t2);
+            t2 = (B.List_MMm[t2] & 1 << (char & 15)) === 0;
           } else
             t2 = true;
           if (t2)
@@ -5685,9 +5935,12 @@
       return t1.charCodeAt(0) == 0 ? t1 : t1;
     },
     _Uri__hexCharPairToByte(s, pos) {
-      var byte, i, charCode;
-      for (byte = 0, i = 0; i < 2; ++i) {
-        charCode = B.JSString_methods._codeUnitAt$1(s, pos + i);
+      var t1, byte, i, t2, charCode;
+      for (t1 = s.length, byte = 0, i = 0; i < 2; ++i) {
+        t2 = pos + i;
+        if (!(t2 < t1))
+          return A.ioore(s, t2);
+        charCode = s.charCodeAt(t2);
         if (48 <= charCode && charCode <= 57)
           byte = byte * 16 + charCode - 48;
         else {
@@ -5701,22 +5954,25 @@
       return byte;
     },
     _Uri__uriDecode(text, start, end, encoding, plusToSpace) {
-      var simple, codeUnit, t1, bytes,
+      var simple, codeUnit, t2, bytes,
+        t1 = text.length,
         i = start;
       while (true) {
         if (!(i < end)) {
           simple = true;
           break;
         }
-        codeUnit = B.JSString_methods._codeUnitAt$1(text, i);
+        if (!(i < t1))
+          return A.ioore(text, i);
+        codeUnit = text.charCodeAt(i);
         if (codeUnit <= 127)
           if (codeUnit !== 37)
-            t1 = plusToSpace && codeUnit === 43;
+            t2 = plusToSpace && codeUnit === 43;
           else
-            t1 = true;
+            t2 = true;
         else
-          t1 = true;
-        if (t1) {
+          t2 = true;
+        if (t2) {
           simple = false;
           break;
         }
@@ -5733,8 +5989,10 @@
           bytes = new A.CodeUnits(B.JSString_methods.substring$2(text, start, end));
       } else {
         bytes = A._setArrayType([], type$.JSArray_int);
-        for (t1 = text.length, i = start; i < end; ++i) {
-          codeUnit = B.JSString_methods._codeUnitAt$1(text, i);
+        for (i = start; i < end; ++i) {
+          if (!(i < t1))
+            return A.ioore(text, i);
+          codeUnit = text.charCodeAt(i);
           if (codeUnit > 127)
             throw A.wrapException(A.ArgumentError$("Illegal percent encoding in URI", null));
           if (codeUnit === 37) {
@@ -5763,15 +6021,15 @@
         slashIndex = A.UriData__validateMimeType("");
         if (slashIndex < 0)
           throw A.wrapException(A.ArgumentError$value("", "mimeType", "Invalid MIME type"));
-        t1 = buffer._contents += A._Uri__uriEncode(B.List_qFt, B.JSString_methods.substring$2("", 0, slashIndex), B.C_Utf8Codec, false);
+        t1 = buffer._contents += A._Uri__uriEncode(B.List_yzX, B.JSString_methods.substring$2("", 0, slashIndex), B.C_Utf8Codec, false);
         buffer._contents = t1 + "/";
-        buffer._contents += A._Uri__uriEncode(B.List_qFt, B.JSString_methods.substring$1("", slashIndex + 1), B.C_Utf8Codec, false);
+        buffer._contents += A._Uri__uriEncode(B.List_yzX, B.JSString_methods.substring$1("", slashIndex + 1), B.C_Utf8Codec, false);
       }
     },
     UriData__validateMimeType(mimeType) {
       var t1, slashIndex, i;
       for (t1 = mimeType.length, slashIndex = -1, i = 0; i < t1; ++i) {
-        if (B.JSString_methods._codeUnitAt$1(mimeType, i) !== 47)
+        if (mimeType.charCodeAt(i) !== 47)
           continue;
         if (slashIndex < 0) {
           slashIndex = i;
@@ -5786,7 +6044,7 @@
         _s17_ = "Invalid MIME type",
         indices = A._setArrayType([start - 1], type$.JSArray_int);
       for (t1 = text.length, i = start, slashIndex = -1, char = null; i < t1; ++i) {
-        char = B.JSString_methods._codeUnitAt$1(text, i);
+        char = text.charCodeAt(i);
         if (char === 44 || char === 59)
           break;
         if (char === 47) {
@@ -5803,7 +6061,9 @@
         B.JSArray_methods.add$1(indices, i);
         ++i;
         for (equalsIndex = -1; i < t1; ++i) {
-          char = B.JSString_methods._codeUnitAt$1(text, i);
+          if (!(i >= 0))
+            return A.ioore(text, i);
+          char = text.charCodeAt(i);
           if (char === 61) {
             if (equalsIndex < 0)
               equalsIndex = i;
@@ -5824,183 +6084,198 @@
       if ((indices.length & 1) === 1)
         text = B.C_Base64Codec.normalize$3(0, text, t2, t1);
       else {
-        data = A._Uri__normalize(text, t2, t1, B.List_CVk, true);
+        data = A._Uri__normalize(text, t2, t1, B.List_oFp, true, false);
         if (data != null)
           text = B.JSString_methods.replaceRange$3(text, t2, t1, data);
       }
       return new A.UriData(text, indices, sourceUri);
     },
     UriData__uriEncodeBytes(canonicalTable, bytes, buffer) {
-      var t1, byteOr, i, byte, t2, t3,
+      var t1, byteOr, i, byte, t2,
         _s16_ = "0123456789ABCDEF";
-      for (t1 = J.getInterceptor$asx(bytes), byteOr = 0, i = 0; i < t1.get$length(bytes); ++i) {
-        byte = t1.$index(bytes, i);
+      for (t1 = bytes.length, byteOr = 0, i = 0; i < t1; ++i) {
+        byte = bytes[i];
         byteOr |= byte;
         if (byte < 128) {
-          t2 = B.JSInt_methods._shrOtherPositive$1(byte, 4);
+          t2 = byte >>> 4;
           if (!(t2 < 8))
             return A.ioore(canonicalTable, t2);
           t2 = (canonicalTable[t2] & 1 << (byte & 15)) !== 0;
         } else
           t2 = false;
-        t3 = buffer._contents;
         if (t2)
-          buffer._contents = t3 + A.Primitives_stringFromCharCode(byte);
+          buffer._contents += A.Primitives_stringFromCharCode(byte);
         else {
-          t2 = t3 + A.Primitives_stringFromCharCode(37);
-          buffer._contents = t2;
-          t2 += A.Primitives_stringFromCharCode(B.JSString_methods._codeUnitAt$1(_s16_, B.JSInt_methods._shrOtherPositive$1(byte, 4)));
-          buffer._contents = t2;
-          buffer._contents = t2 + A.Primitives_stringFromCharCode(B.JSString_methods._codeUnitAt$1(_s16_, byte & 15));
+          buffer._contents += A.Primitives_stringFromCharCode(37);
+          t2 = byte >>> 4;
+          if (!(t2 < 16))
+            return A.ioore(_s16_, t2);
+          buffer._contents += A.Primitives_stringFromCharCode(_s16_.charCodeAt(t2));
+          buffer._contents += A.Primitives_stringFromCharCode(_s16_.charCodeAt(byte & 15));
         }
       }
-      if ((byteOr & 4294967040) >>> 0 !== 0)
-        for (i = 0; i < t1.get$length(bytes); ++i) {
-          byte = t1.$index(bytes, i);
-          if (byte < 0 || byte > 255)
+      if ((byteOr & 4294967040) !== 0)
+        for (i = 0; i < t1; ++i) {
+          byte = bytes[i];
+          if (byte > 255)
             throw A.wrapException(A.ArgumentError$value(byte, "non-byte value", null));
         }
     },
     _createTables() {
-      var _i, t1, t2, t3, t4, b,
+      var _i, t1, t2, t3, t4, t5,
         _s77_ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$&'()*+,;=",
-        _s1_ = ".", _s1_0 = ":", _s1_1 = "/", _s1_2 = "?", _s1_3 = "#",
+        _s1_ = ".", _s1_0 = ":", _s1_1 = "/", _s1_2 = "\\", _s1_3 = "?", _s1_4 = "#", _s2_ = "/\\",
         tables = A._setArrayType(new Array(22), type$.JSArray_Uint8List);
       for (_i = 0; _i < 22; ++_i)
         tables[_i] = new Uint8Array(96);
       t1 = new A._createTables_build(tables);
       t2 = new A._createTables_setChars();
       t3 = new A._createTables_setRange();
-      t4 = type$.Uint8List._as(t1.call$2(0, 225));
-      t2.call$3(t4, _s77_, 1);
-      t2.call$3(t4, _s1_, 14);
-      t2.call$3(t4, _s1_0, 34);
-      t2.call$3(t4, _s1_1, 3);
-      t2.call$3(t4, _s1_2, 172);
-      t2.call$3(t4, _s1_3, 205);
-      b = t1.call$2(14, 225);
-      t2.call$3(b, _s77_, 1);
-      t2.call$3(b, _s1_, 15);
-      t2.call$3(b, _s1_0, 34);
-      t2.call$3(b, _s1_1, 234);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(15, 225);
-      t2.call$3(b, _s77_, 1);
-      t2.call$3(b, "%", 225);
-      t2.call$3(b, _s1_0, 34);
-      t2.call$3(b, _s1_1, 9);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(1, 225);
-      t2.call$3(b, _s77_, 1);
-      t2.call$3(b, _s1_0, 34);
-      t2.call$3(b, _s1_1, 10);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(2, 235);
-      t2.call$3(b, _s77_, 139);
-      t2.call$3(b, _s1_1, 131);
-      t2.call$3(b, _s1_, 146);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(3, 235);
-      t2.call$3(b, _s77_, 11);
-      t2.call$3(b, _s1_1, 68);
-      t2.call$3(b, _s1_, 18);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(4, 229);
-      t2.call$3(b, _s77_, 5);
-      t3.call$3(b, "AZ", 229);
-      t2.call$3(b, _s1_0, 102);
-      t2.call$3(b, "@", 68);
-      t2.call$3(b, "[", 232);
-      t2.call$3(b, _s1_1, 138);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(5, 229);
-      t2.call$3(b, _s77_, 5);
-      t3.call$3(b, "AZ", 229);
-      t2.call$3(b, _s1_0, 102);
-      t2.call$3(b, "@", 68);
-      t2.call$3(b, _s1_1, 138);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(6, 231);
-      t3.call$3(b, "19", 7);
-      t2.call$3(b, "@", 68);
-      t2.call$3(b, _s1_1, 138);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(7, 231);
-      t3.call$3(b, "09", 7);
-      t2.call$3(b, "@", 68);
-      t2.call$3(b, _s1_1, 138);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      t2.call$3(t1.call$2(8, 8), "]", 5);
-      b = t1.call$2(9, 235);
-      t2.call$3(b, _s77_, 11);
-      t2.call$3(b, _s1_, 16);
-      t2.call$3(b, _s1_1, 234);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(16, 235);
-      t2.call$3(b, _s77_, 11);
-      t2.call$3(b, _s1_, 17);
-      t2.call$3(b, _s1_1, 234);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(17, 235);
-      t2.call$3(b, _s77_, 11);
-      t2.call$3(b, _s1_1, 9);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(10, 235);
-      t2.call$3(b, _s77_, 11);
-      t2.call$3(b, _s1_, 18);
-      t2.call$3(b, _s1_1, 234);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(18, 235);
-      t2.call$3(b, _s77_, 11);
-      t2.call$3(b, _s1_, 19);
-      t2.call$3(b, _s1_1, 234);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(19, 235);
-      t2.call$3(b, _s77_, 11);
-      t2.call$3(b, _s1_1, 234);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(11, 235);
-      t2.call$3(b, _s77_, 11);
-      t2.call$3(b, _s1_1, 10);
-      t2.call$3(b, _s1_2, 172);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(12, 236);
-      t2.call$3(b, _s77_, 12);
-      t2.call$3(b, _s1_2, 12);
-      t2.call$3(b, _s1_3, 205);
-      b = t1.call$2(13, 237);
-      t2.call$3(b, _s77_, 13);
-      t2.call$3(b, _s1_2, 13);
-      t3.call$3(t1.call$2(20, 245), "az", 21);
-      b = t1.call$2(21, 245);
-      t3.call$3(b, "az", 21);
-      t3.call$3(b, "09", 21);
-      t2.call$3(b, "+-.", 21);
+      t4 = type$.Uint8List;
+      t5 = t4._as(t1.call$2(0, 225));
+      t2.call$3(t5, _s77_, 1);
+      t2.call$3(t5, _s1_, 14);
+      t2.call$3(t5, _s1_0, 34);
+      t2.call$3(t5, _s1_1, 3);
+      t2.call$3(t5, _s1_2, 227);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(14, 225));
+      t2.call$3(t5, _s77_, 1);
+      t2.call$3(t5, _s1_, 15);
+      t2.call$3(t5, _s1_0, 34);
+      t2.call$3(t5, _s2_, 234);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(15, 225));
+      t2.call$3(t5, _s77_, 1);
+      t2.call$3(t5, "%", 225);
+      t2.call$3(t5, _s1_0, 34);
+      t2.call$3(t5, _s1_1, 9);
+      t2.call$3(t5, _s1_2, 233);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(1, 225));
+      t2.call$3(t5, _s77_, 1);
+      t2.call$3(t5, _s1_0, 34);
+      t2.call$3(t5, _s1_1, 10);
+      t2.call$3(t5, _s1_2, 234);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(2, 235));
+      t2.call$3(t5, _s77_, 139);
+      t2.call$3(t5, _s1_1, 131);
+      t2.call$3(t5, _s1_2, 131);
+      t2.call$3(t5, _s1_, 146);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(3, 235));
+      t2.call$3(t5, _s77_, 11);
+      t2.call$3(t5, _s1_1, 68);
+      t2.call$3(t5, _s1_2, 68);
+      t2.call$3(t5, _s1_, 18);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(4, 229));
+      t2.call$3(t5, _s77_, 5);
+      t3.call$3(t5, "AZ", 229);
+      t2.call$3(t5, _s1_0, 102);
+      t2.call$3(t5, "@", 68);
+      t2.call$3(t5, "[", 232);
+      t2.call$3(t5, _s1_1, 138);
+      t2.call$3(t5, _s1_2, 138);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(5, 229));
+      t2.call$3(t5, _s77_, 5);
+      t3.call$3(t5, "AZ", 229);
+      t2.call$3(t5, _s1_0, 102);
+      t2.call$3(t5, "@", 68);
+      t2.call$3(t5, _s1_1, 138);
+      t2.call$3(t5, _s1_2, 138);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(6, 231));
+      t3.call$3(t5, "19", 7);
+      t2.call$3(t5, "@", 68);
+      t2.call$3(t5, _s1_1, 138);
+      t2.call$3(t5, _s1_2, 138);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(7, 231));
+      t3.call$3(t5, "09", 7);
+      t2.call$3(t5, "@", 68);
+      t2.call$3(t5, _s1_1, 138);
+      t2.call$3(t5, _s1_2, 138);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t2.call$3(t4._as(t1.call$2(8, 8)), "]", 5);
+      t5 = t4._as(t1.call$2(9, 235));
+      t2.call$3(t5, _s77_, 11);
+      t2.call$3(t5, _s1_, 16);
+      t2.call$3(t5, _s2_, 234);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(16, 235));
+      t2.call$3(t5, _s77_, 11);
+      t2.call$3(t5, _s1_, 17);
+      t2.call$3(t5, _s2_, 234);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(17, 235));
+      t2.call$3(t5, _s77_, 11);
+      t2.call$3(t5, _s1_1, 9);
+      t2.call$3(t5, _s1_2, 233);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(10, 235));
+      t2.call$3(t5, _s77_, 11);
+      t2.call$3(t5, _s1_, 18);
+      t2.call$3(t5, _s1_1, 10);
+      t2.call$3(t5, _s1_2, 234);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(18, 235));
+      t2.call$3(t5, _s77_, 11);
+      t2.call$3(t5, _s1_, 19);
+      t2.call$3(t5, _s2_, 234);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(19, 235));
+      t2.call$3(t5, _s77_, 11);
+      t2.call$3(t5, _s2_, 234);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(11, 235));
+      t2.call$3(t5, _s77_, 11);
+      t2.call$3(t5, _s1_1, 10);
+      t2.call$3(t5, _s1_2, 234);
+      t2.call$3(t5, _s1_3, 172);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(12, 236));
+      t2.call$3(t5, _s77_, 12);
+      t2.call$3(t5, _s1_3, 12);
+      t2.call$3(t5, _s1_4, 205);
+      t5 = t4._as(t1.call$2(13, 237));
+      t2.call$3(t5, _s77_, 13);
+      t2.call$3(t5, _s1_3, 13);
+      t3.call$3(t4._as(t1.call$2(20, 245)), "az", 21);
+      t1 = t4._as(t1.call$2(21, 245));
+      t3.call$3(t1, "az", 21);
+      t3.call$3(t1, "09", 21);
+      t2.call$3(t1, "+-.", 21);
       return tables;
     },
     _scan(uri, start, end, state, indices) {
-      var i, table, char, transition,
+      var t1, i, table, char, transition,
         tables = $.$get$_scannerTables();
-      for (i = start; i < end; ++i) {
+      for (t1 = uri.length, i = start; i < end; ++i) {
         if (!(state >= 0 && state < tables.length))
           return A.ioore(tables, state);
         table = tables[state];
-        char = B.JSString_methods._codeUnitAt$1(uri, i) ^ 96;
+        if (!(i < t1))
+          return A.ioore(uri, i);
+        char = uri.charCodeAt(i) ^ 96;
         transition = table[char > 95 ? 31 : char];
         state = transition & 31;
         B.JSArray_methods.$indexSet(indices, transition >>> 5, i);
@@ -6013,9 +6288,11 @@
       return -1;
     },
     _skipPackageNameChars(source, start, end) {
-      var i, dots, char;
-      for (i = start, dots = 0; i < end; ++i) {
-        char = B.JSString_methods.codeUnitAt$1(source, i);
+      var t1, i, dots, char;
+      for (t1 = source.length, i = start, dots = 0; i < end; ++i) {
+        if (!(i >= 0 && i < t1))
+          return A.ioore(source, i);
+        char = source.charCodeAt(i);
         if (char === 47)
           return dots !== 0 ? i : -1;
         if (char === 37 || char === 58)
@@ -6025,11 +6302,13 @@
       return -1;
     },
     _caseInsensitiveCompareStart(prefix, string, start) {
-      var t1, result, i, prefixChar, stringChar, delta, lowerChar;
-      for (t1 = prefix.length, result = 0, i = 0; i < t1; ++i) {
-        prefixChar = B.JSString_methods._codeUnitAt$1(prefix, i);
-        stringChar = B.JSString_methods._codeUnitAt$1(string, start + i);
-        delta = prefixChar ^ stringChar;
+      var t1, t2, result, i, t3, stringChar, delta, lowerChar;
+      for (t1 = prefix.length, t2 = string.length, result = 0, i = 0; i < t1; ++i) {
+        t3 = start + i;
+        if (!(t3 < t2))
+          return A.ioore(string, t3);
+        stringChar = string.charCodeAt(t3);
+        delta = prefix.charCodeAt(i) ^ stringChar;
         if (delta !== 0) {
           if (delta === 32) {
             lowerChar = stringChar | delta;
@@ -6048,7 +6327,7 @@
       this.sb = t1;
     },
     DateTime: function DateTime(t0, t1) {
-      this._value = t0;
+      this._core$_value = t0;
       this.isUtc = t1;
     },
     Duration: function Duration(t0) {
@@ -6061,8 +6340,6 @@
     },
     TypeError: function TypeError() {
     },
-    NullThrownError: function NullThrownError() {
-    },
     ArgumentError: function ArgumentError(t0, t1, t2, t3) {
       var _ = this;
       _._hasValue = t0;
@@ -6110,9 +6387,6 @@
     },
     StackOverflowError: function StackOverflowError() {
     },
-    CyclicInitializationError: function CyclicInitializationError(t0) {
-      this.variableName = t0;
-    },
     _Exception: function _Exception(t0) {
       this.message = t0;
     },
@@ -6123,8 +6397,6 @@
     },
     Iterable: function Iterable() {
     },
-    Iterator: function Iterator() {
-    },
     Null: function Null() {
     },
     Object: function Object() {
@@ -6424,10 +6696,38 @@
     },
     __StyleSheetList_JavaScriptObject_ListMixin_ImmutableListMixin: function __StyleSheetList_JavaScriptObject_ListMixin_ImmutableListMixin() {
     },
-    _convertDataTree(data) {
-      var t1 = new A._convertDataTree__convert(new A._IdentityHashMap(type$._IdentityHashMap_dynamic_dynamic)).call$1(data);
-      t1.toString;
-      return t1;
+    _convertDartFunctionFast(f) {
+      var ret,
+        existing = f.$dart_jsFunction;
+      if (existing != null)
+        return existing;
+      ret = function(_call, f) {
+        return function() {
+          return _call(f, Array.prototype.slice.apply(arguments));
+        };
+      }(A._callDartFunctionFast, f);
+      ret[$.$get$DART_CLOSURE_PROPERTY_NAME()] = f;
+      f.$dart_jsFunction = ret;
+      return ret;
+    },
+    _callDartFunctionFast(callback, $arguments) {
+      type$.List_dynamic._as($arguments);
+      type$.Function._as(callback);
+      return A.Primitives_applyFunction(callback, $arguments, null);
+    },
+    allowInterop(f, $F) {
+      if (typeof f == "function")
+        return f;
+      else
+        return $F._as(A._convertDartFunctionFast(f));
+    },
+    _noJsifyRequired(o) {
+      return o == null || A._isBool(o) || typeof o == "number" || typeof o == "string" || type$.Int8List._is(o) || type$.Uint8List._is(o) || type$.Uint8ClampedList._is(o) || type$.Int16List._is(o) || type$.Uint16List._is(o) || type$.Int32List._is(o) || type$.Uint32List._is(o) || type$.Float32List._is(o) || type$.Float64List._is(o) || type$.ByteBuffer._is(o) || type$.ByteData._is(o);
+    },
+    jsify(object) {
+      if (A._noJsifyRequired(object))
+        return object;
+      return new A.jsify__convert(new A._IdentityHashMap(type$._IdentityHashMap_of_nullable_Object_and_nullable_Object)).call$1(object);
     },
     getProperty(o, $name, $T) {
       return $T._as(o[$name]);
@@ -6462,10 +6762,15 @@
       jsPromise.then(A.convertDartClosureToJS(new A.promiseToFuture_closure(completer, $T), 1), A.convertDartClosureToJS(new A.promiseToFuture_closure0(completer), 1));
       return t1;
     },
-    dartify(o) {
-      return new A.dartify_convert(new A._IdentityHashMap(type$._IdentityHashMap_dynamic_dynamic)).call$1(o);
+    _noDartifyRequired(o) {
+      return o == null || typeof o === "boolean" || typeof o === "number" || typeof o === "string" || o instanceof Int8Array || o instanceof Uint8Array || o instanceof Uint8ClampedArray || o instanceof Int16Array || o instanceof Uint16Array || o instanceof Int32Array || o instanceof Uint32Array || o instanceof Float32Array || o instanceof Float64Array || o instanceof ArrayBuffer || o instanceof DataView;
     },
-    _convertDataTree__convert: function _convertDataTree__convert(t0) {
+    dartify(o) {
+      if (A._noDartifyRequired(o))
+        return o;
+      return new A.dartify_convert(new A._IdentityHashMap(type$._IdentityHashMap_of_nullable_Object_and_nullable_Object)).call$1(o);
+    },
+    jsify__convert: function jsify__convert(t0) {
       this._convertedObjects = t0;
     },
     promiseToFuture_closure: function promiseToFuture_closure(t0, t1) {
@@ -6538,10 +6843,7 @@
       this.$this = t0;
     },
     Context_Context(style) {
-      var current = style == null ? A.current() : ".";
-      if (style == null)
-        style = $.$get$Style_platform();
-      return new A.Context(type$.InternalStyle._as(style), current);
+      return new A.Context(style, ".");
     },
     _parseUri(uri) {
       return uri;
@@ -6582,7 +6884,7 @@
     InternalStyle: function InternalStyle() {
     },
     ParsedPath_ParsedPath$parse(path, style) {
-      var t1, parts, separators, start, i,
+      var t1, parts, separators, t2, start, i,
         root = style.getRoot$1(path);
       style.isRootRelative$1(path);
       if (root != null)
@@ -6591,7 +6893,13 @@
       parts = A._setArrayType([], t1);
       separators = A._setArrayType([], t1);
       t1 = path.length;
-      if (t1 !== 0 && style.isSeparator$1(B.JSString_methods._codeUnitAt$1(path, 0))) {
+      if (t1 !== 0) {
+        if (0 >= t1)
+          return A.ioore(path, 0);
+        t2 = style.isSeparator$1(path.charCodeAt(0));
+      } else
+        t2 = false;
+      if (t2) {
         if (0 >= t1)
           return A.ioore(path, 0);
         B.JSArray_methods.add$1(separators, path[0]);
@@ -6601,7 +6909,7 @@
         start = 0;
       }
       for (i = start; i < t1; ++i)
-        if (style.isSeparator$1(B.JSString_methods._codeUnitAt$1(path, i))) {
+        if (style.isSeparator$1(path.charCodeAt(i))) {
           B.JSArray_methods.add$1(parts, B.JSString_methods.substring$2(path, start, i));
           B.JSArray_methods.add$1(separators, path[i]);
           start = i + 1;
@@ -6660,28 +6968,24 @@
     },
     Chain_Chain$parse(chain) {
       var t1, t2,
-        _s51_ = string$.______;
+        _s51_ = string$.x3d_____;
       if (chain.length === 0)
         return new A.Chain(A.List_List$unmodifiable(A._setArrayType([], type$.JSArray_Trace), type$.Trace));
       t1 = $.$get$vmChainGap();
       if (B.JSString_methods.contains$1(chain, t1)) {
         t1 = B.JSString_methods.split$1(chain, t1);
         t2 = A._arrayInstanceType(t1);
-        return new A.Chain(A.List_List$unmodifiable(new A.MappedIterable(new A.WhereIterable(t1, t2._eval$1("bool(1)")._as(new A.Chain_Chain$parse_closure()), t2._eval$1("WhereIterable<1>")), t2._eval$1("Trace(1)")._as(new A.Chain_Chain$parse_closure0()), t2._eval$1("MappedIterable<1,Trace>")), type$.Trace));
+        return new A.Chain(A.List_List$unmodifiable(new A.MappedIterable(new A.WhereIterable(t1, t2._eval$1("bool(1)")._as(new A.Chain_Chain$parse_closure()), t2._eval$1("WhereIterable<1>")), t2._eval$1("Trace(1)")._as(A.trace_Trace___parseVM_tearOff$closure()), t2._eval$1("MappedIterable<1,Trace>")), type$.Trace));
       }
       if (!B.JSString_methods.contains$1(chain, _s51_))
         return new A.Chain(A.List_List$unmodifiable(A._setArrayType([A.Trace_Trace$parse(chain)], type$.JSArray_Trace), type$.Trace));
-      return new A.Chain(A.List_List$unmodifiable(new A.MappedListIterable(A._setArrayType(chain.split(_s51_), type$.JSArray_String), type$.Trace_Function_String._as(new A.Chain_Chain$parse_closure1()), type$.MappedListIterable_String_Trace), type$.Trace));
+      return new A.Chain(A.List_List$unmodifiable(new A.MappedListIterable(A._setArrayType(chain.split(_s51_), type$.JSArray_String), type$.Trace_Function_String._as(A.trace_Trace___parseFriendly_tearOff$closure()), type$.MappedListIterable_String_Trace), type$.Trace));
     },
     Chain: function Chain(t0) {
       this.traces = t0;
     },
     Chain_Chain$parse_closure: function Chain_Chain$parse_closure() {
     },
-    Chain_Chain$parse_closure0: function Chain_Chain$parse_closure0() {
-    },
-    Chain_Chain$parse_closure1: function Chain_Chain$parse_closure1() {
-    },
     Chain_toTrace_closure: function Chain_toTrace_closure() {
     },
     Chain_toString_closure0: function Chain_toString_closure0() {
@@ -6694,18 +6998,30 @@
     Chain_toString__closure: function Chain_toString__closure(t0) {
       this.longest = t0;
     },
+    Frame___parseVM_tearOff(frame) {
+      return A.Frame_Frame$parseVM(A._asString(frame));
+    },
     Frame_Frame$parseVM(frame) {
       return A.Frame__catchFormatException(frame, new A.Frame_Frame$parseVM_closure(frame));
     },
+    Frame___parseV8_tearOff(frame) {
+      return A.Frame_Frame$parseV8(A._asString(frame));
+    },
     Frame_Frame$parseV8(frame) {
       return A.Frame__catchFormatException(frame, new A.Frame_Frame$parseV8_closure(frame));
     },
     Frame_Frame$_parseFirefoxEval(frame) {
       return A.Frame__catchFormatException(frame, new A.Frame_Frame$_parseFirefoxEval_closure(frame));
     },
+    Frame___parseFirefox_tearOff(frame) {
+      return A.Frame_Frame$parseFirefox(A._asString(frame));
+    },
     Frame_Frame$parseFirefox(frame) {
       return A.Frame__catchFormatException(frame, new A.Frame_Frame$parseFirefox_closure(frame));
     },
+    Frame___parseFriendly_tearOff(frame) {
+      return A.Frame_Frame$parseFriendly(A._asString(frame));
+    },
     Frame_Frame$parseFriendly(frame) {
       return A.Frame__catchFormatException(frame, new A.Frame_Frame$parseFriendly_closure(frame));
     },
@@ -6790,7 +7106,7 @@
           t1 = A.Trace$parseFirefox(trace);
           return t1;
         }
-        if (B.JSString_methods.contains$1(trace, string$.______)) {
+        if (B.JSString_methods.contains$1(trace, string$.x3d_____)) {
           t1 = A.Chain_Chain$parse(trace).toTrace$0();
           return t1;
         }
@@ -6809,6 +7125,9 @@
           throw exception;
       }
     },
+    Trace___parseVM_tearOff(trace) {
+      return A.Trace$parseVM(A._asString(trace));
+    },
     Trace$parseVM(trace) {
       var t1 = A.List_List$unmodifiable(A.Trace__parseVM(trace), type$.Frame);
       return new A.Trace(t1, new A._StringStackTrace(trace));
@@ -6816,14 +7135,14 @@
     Trace__parseVM(trace) {
       var $frames,
         t1 = B.JSString_methods.trim$0(trace),
-        t2 = type$.Pattern._as($.$get$vmChainGap()),
+        t2 = $.$get$vmChainGap(),
         t3 = type$.WhereIterable_String,
         lines = new A.WhereIterable(A._setArrayType(A.stringReplaceAllUnchecked(t1, t2, "").split("\n"), type$.JSArray_String), type$.bool_Function_String._as(new A.Trace__parseVM_closure()), t3);
       if (!lines.get$iterator(lines).moveNext$0())
         return A._setArrayType([], type$.JSArray_Frame);
       t1 = A.TakeIterable_TakeIterable(lines, lines.get$length(lines) - 1, t3._eval$1("Iterable.E"));
       t2 = A._instanceType(t1);
-      t2 = A.MappedIterable_MappedIterable(t1, t2._eval$1("Frame(Iterable.E)")._as(new A.Trace__parseVM_closure0()), t2._eval$1("Iterable.E"), type$.Frame);
+      t2 = A.MappedIterable_MappedIterable(t1, t2._eval$1("Frame(Iterable.E)")._as(A.frame_Frame___parseVM_tearOff$closure()), t2._eval$1("Iterable.E"), type$.Frame);
       $frames = A.List_List$of(t2, true, A._instanceType(t2)._eval$1("Iterable.E"));
       if (!J.endsWith$1$s(lines.get$last(lines), ".da"))
         B.JSArray_methods.add$1($frames, A.Frame_Frame$parseVM(lines.get$last(lines)));
@@ -6835,19 +7154,22 @@
       t1 = t1.super$Iterable$skipWhile(0, t1.$ti._eval$1("bool(ListIterable.E)")._as(new A.Trace$parseV8_closure()));
       t2 = type$.Frame;
       t3 = t1.$ti;
-      t2 = A.List_List$unmodifiable(A.MappedIterable_MappedIterable(t1, t3._eval$1("Frame(Iterable.E)")._as(new A.Trace$parseV8_closure0()), t3._eval$1("Iterable.E"), t2), t2);
+      t2 = A.List_List$unmodifiable(A.MappedIterable_MappedIterable(t1, t3._eval$1("Frame(Iterable.E)")._as(A.frame_Frame___parseV8_tearOff$closure()), t3._eval$1("Iterable.E"), t2), t2);
       return new A.Trace(t2, new A._StringStackTrace(trace));
     },
     Trace$parseJSCore(trace) {
-      var t1 = A.List_List$unmodifiable(new A.MappedIterable(new A.WhereIterable(A._setArrayType(trace.split("\n"), type$.JSArray_String), type$.bool_Function_String._as(new A.Trace$parseJSCore_closure()), type$.WhereIterable_String), type$.Frame_Function_String._as(new A.Trace$parseJSCore_closure0()), type$.MappedIterable_String_Frame), type$.Frame);
+      var t1 = A.List_List$unmodifiable(new A.MappedIterable(new A.WhereIterable(A._setArrayType(trace.split("\n"), type$.JSArray_String), type$.bool_Function_String._as(new A.Trace$parseJSCore_closure()), type$.WhereIterable_String), type$.Frame_Function_String._as(A.frame_Frame___parseV8_tearOff$closure()), type$.MappedIterable_String_Frame), type$.Frame);
       return new A.Trace(t1, new A._StringStackTrace(trace));
     },
     Trace$parseFirefox(trace) {
-      var t1 = A.List_List$unmodifiable(new A.MappedIterable(new A.WhereIterable(A._setArrayType(B.JSString_methods.trim$0(trace).split("\n"), type$.JSArray_String), type$.bool_Function_String._as(new A.Trace$parseFirefox_closure()), type$.WhereIterable_String), type$.Frame_Function_String._as(new A.Trace$parseFirefox_closure0()), type$.MappedIterable_String_Frame), type$.Frame);
+      var t1 = A.List_List$unmodifiable(new A.MappedIterable(new A.WhereIterable(A._setArrayType(B.JSString_methods.trim$0(trace).split("\n"), type$.JSArray_String), type$.bool_Function_String._as(new A.Trace$parseFirefox_closure()), type$.WhereIterable_String), type$.Frame_Function_String._as(A.frame_Frame___parseFirefox_tearOff$closure()), type$.MappedIterable_String_Frame), type$.Frame);
       return new A.Trace(t1, new A._StringStackTrace(trace));
     },
+    Trace___parseFriendly_tearOff(trace) {
+      return A.Trace$parseFriendly(A._asString(trace));
+    },
     Trace$parseFriendly(trace) {
-      var t1 = trace.length === 0 ? A._setArrayType([], type$.JSArray_Frame) : new A.MappedIterable(new A.WhereIterable(A._setArrayType(B.JSString_methods.trim$0(trace).split("\n"), type$.JSArray_String), type$.bool_Function_String._as(new A.Trace$parseFriendly_closure()), type$.WhereIterable_String), type$.Frame_Function_String._as(new A.Trace$parseFriendly_closure0()), type$.MappedIterable_String_Frame);
+      var t1 = trace.length === 0 ? A._setArrayType([], type$.JSArray_Frame) : new A.MappedIterable(new A.WhereIterable(A._setArrayType(B.JSString_methods.trim$0(trace).split("\n"), type$.JSArray_String), type$.bool_Function_String._as(new A.Trace$parseFriendly_closure()), type$.WhereIterable_String), type$.Frame_Function_String._as(A.frame_Frame___parseFriendly_tearOff$closure()), type$.MappedIterable_String_Frame);
       t1 = A.List_List$unmodifiable(t1, type$.Frame);
       return new A.Trace(t1, new A._StringStackTrace(trace));
     },
@@ -6864,24 +7186,14 @@
     },
     Trace__parseVM_closure: function Trace__parseVM_closure() {
     },
-    Trace__parseVM_closure0: function Trace__parseVM_closure0() {
-    },
     Trace$parseV8_closure: function Trace$parseV8_closure() {
     },
-    Trace$parseV8_closure0: function Trace$parseV8_closure0() {
-    },
     Trace$parseJSCore_closure: function Trace$parseJSCore_closure() {
     },
-    Trace$parseJSCore_closure0: function Trace$parseJSCore_closure0() {
-    },
     Trace$parseFirefox_closure: function Trace$parseFirefox_closure() {
     },
-    Trace$parseFirefox_closure0: function Trace$parseFirefox_closure0() {
-    },
     Trace$parseFriendly_closure: function Trace$parseFriendly_closure() {
     },
-    Trace$parseFriendly_closure0: function Trace$parseFriendly_closure0() {
-    },
     Trace_terse_closure: function Trace_terse_closure() {
     },
     Trace_foldFrames_closure: function Trace_foldFrames_closure(t0) {
@@ -7002,13 +7314,17 @@
     },
     StreamChannelMixin: function StreamChannelMixin() {
     },
-    WindowExtension_get_location(_this) {
-      return type$.JavaScriptObject._as(_this.location);
-    },
     EventTargetExtension_addEventListener(_this, type, listener) {
       var t1 = A._setArrayType([type, listener], type$.JSArray_Object);
       A.callMethod(_this, "addEventListener", t1, type$.dynamic);
     },
+    EventTargetExtension_removeEventListener(_this, type, listener) {
+      var t1 = A._setArrayType([type, listener], type$.JSArray_Object);
+      A.callMethod(_this, "removeEventListener", t1, type$.dynamic);
+    },
+    MessagePortExtension_get_postMessage(_this) {
+      return new A.MessagePortExtension_get_postMessage_closure(_this);
+    },
     _callConstructor(constructorName, args) {
       var $constructor = self.window[constructorName];
       if ($constructor == null)
@@ -7019,43 +7335,8 @@
       A.EventTargetExtension_addEventListener(target, type, listener);
       return new A.Subscription(type, target, listener);
     },
-    Window0: function Window0() {
-    },
-    Document0: function Document0() {
-    },
-    HTMLDocument: function HTMLDocument() {
-    },
-    Navigator0: function Navigator0() {
-    },
-    Element0: function Element0() {
-    },
-    HTMLElement: function HTMLElement() {
-    },
-    HTMLBodyElement: function HTMLBodyElement() {
-    },
-    Node0: function Node0() {
-    },
-    EventTarget0: function EventTarget0() {
-    },
-    Event0: function Event0() {
-    },
-    MessageEvent0: function MessageEvent0() {
-    },
-    Location0: function Location0() {
-    },
-    MessagePort0: function MessagePort0() {
-    },
-    CSSStyleDeclaration: function CSSStyleDeclaration() {
-    },
-    HTMLScriptElement: function HTMLScriptElement() {
-    },
-    DomTokenList0: function DomTokenList0() {
-    },
-    HTMLIFrameElement: function HTMLIFrameElement() {
-    },
-    WebSocket0: function WebSocket0() {
-    },
-    MessageChannel0: function MessageChannel0() {
+    MessagePortExtension_get_postMessage_closure: function MessagePortExtension_get_postMessage_closure(t0) {
+      this._this = t0;
     },
     Subscription: function Subscription(t0, t1, t2) {
       this.type = t0;
@@ -7063,9 +7344,6 @@
       this.listener = t2;
     },
     main() {
-      var t1 = self.testRunner;
-      if (t1 != null)
-        t1.waitUntilDone();
       if (J.$eq$($.$get$_currentUrl().get$queryParameters().$index(0, "debug"), "true"))
         type$.JavaScriptObject._as(type$.nullable_JavaScriptObject._as(self.document.body).classList).add("debug");
       A.runZonedGuarded(new A.main_closure(), new A.main_closure0(), type$.Null);
@@ -7090,41 +7368,21 @@
       return A._MultiChannel$(t1, t2);
     },
     _connectToIframe(url, id) {
-      var controller, readyCompleter, subscriptions, domSubscriptions,
+      var controller, windowSubscription,
         t1 = self.document,
-        t2 = type$.JSArray_Object,
-        t3 = A._setArrayType(["iframe"], t2),
-        t4 = type$.dynamic,
-        t5 = type$.JavaScriptObject,
-        iframe = t5._as(A.callMethod(t1, "createElement", t3, t4));
+        t2 = A._setArrayType(["iframe"], type$.JSArray_Object),
+        t3 = type$.dynamic,
+        t4 = type$.JavaScriptObject,
+        iframe = t4._as(A.callMethod(t1, "createElement", t2, t3));
       $._iframes.$indexSet(0, id, iframe);
+      controller = A.StreamChannelController$(true, t3);
+      windowSubscription = A._Cell$named("windowSubscription");
+      windowSubscription._value = A.Subscription$(self.window, "message", A.allowInterop(new A._connectToIframe_closure(iframe, windowSubscription, id, controller), type$.void_Function_JavaScriptObject));
       iframe.src = url;
-      t5._as(type$.nullable_JavaScriptObject._as(self.document.body).appendChild(iframe));
-      t2 = A._callConstructor("MessageChannel", A._setArrayType([], t2));
-      t2.toString;
-      t5._as(t2);
-      controller = A.StreamChannelController$(true, t4);
-      readyCompleter = new A._AsyncCompleter(new A._Future($.Zone__current, type$._Future_dynamic), type$._AsyncCompleter_dynamic);
-      subscriptions = A._setArrayType([], type$.JSArray_StreamSubscription_void);
-      domSubscriptions = A._setArrayType([], type$.JSArray_Subscription);
-      $._subscriptions.$indexSet(0, id, subscriptions);
-      $._domSubscriptions.$indexSet(0, id, domSubscriptions);
-      t4 = type$.void_Function_JavaScriptObject;
-      B.JSArray_methods.add$1(domSubscriptions, A.Subscription$(self.window, "message", A.allowInterop(new A._connectToIframe_closure(iframe, t2, readyCompleter, controller), t4)));
-      t5._as(t2.port1).start();
-      B.JSArray_methods.add$1(domSubscriptions, A.Subscription$(t5._as(t2.port1), "message", A.allowInterop(new A._connectToIframe_closure0(controller), t4)));
-      t4 = controller.__StreamChannelController__local_F;
-      t4 === $ && A.throwLateFieldNI("_local");
-      t4 = t4.__GuaranteeChannel__streamController_F;
-      t4 === $ && A.throwLateFieldNI("_streamController");
-      B.JSArray_methods.add$1(subscriptions, new A._ControllerStream(t4, A._instanceType(t4)._eval$1("_ControllerStream<1>")).listen$1(new A._connectToIframe_closure1(readyCompleter, t2)));
-      t2 = controller.__StreamChannelController__foreign_F;
-      t2 === $ && A.throwLateFieldNI("_foreign");
-      return t2;
-    },
-    TestRunner: function TestRunner() {
-    },
-    _JSApi: function _JSApi() {
+      t4._as(type$.nullable_JavaScriptObject._as(self.document.body).appendChild(iframe));
+      t4 = controller.__StreamChannelController__foreign_F;
+      t4 === $ && A.throwLateFieldNI("_foreign");
+      return t4;
     },
     main_closure: function main_closure() {
     },
@@ -7154,16 +7412,24 @@
     _connectToIframe_closure: function _connectToIframe_closure(t0, t1, t2, t3) {
       var _ = this;
       _.iframe = t0;
-      _.channel = t1;
-      _.readyCompleter = t2;
+      _.windowSubscription = t1;
+      _.id = t2;
       _.controller = t3;
     },
-    _connectToIframe_closure0: function _connectToIframe_closure0(t0) {
+    _connectToIframe__closure2: function _connectToIframe__closure2(t0) {
       this.controller = t0;
     },
-    _connectToIframe_closure1: function _connectToIframe_closure1(t0, t1) {
-      this.readyCompleter = t0;
-      this.channel = t1;
+    _connectToIframe__closure: function _connectToIframe__closure(t0) {
+      this._0_0 = t0;
+    },
+    _connectToIframe__closure3: function _connectToIframe__closure3(t0) {
+      this.controller = t0;
+    },
+    _connectToIframe__closure0: function _connectToIframe__closure0(t0) {
+      this._0_0 = t0;
+    },
+    _connectToIframe__closure1: function _connectToIframe__closure1(t0) {
+      this._0_0 = t0;
     },
     max(a, b, $T) {
       A.checkTypeBound($T, type$.num, "T", "max");
@@ -7178,8 +7444,6 @@
         console.log(string);
         return;
       }
-      if (typeof window == "object")
-        return;
       if (typeof print == "function") {
         print(string);
         return;
@@ -7187,62 +7451,52 @@
       throw "Unable to print message: " + String(string);
     },
     _convertNativeToDart_Value(value) {
-      var values, i;
+      var proto, t1, values, i;
       if (value == null)
         return value;
       if (typeof value == "string" || typeof value == "number" || A._isBool(value))
         return value;
-      if (A.isJavaScriptSimpleObject(value))
+      proto = Object.getPrototypeOf(value);
+      t1 = proto === Object.prototype;
+      t1.toString;
+      if (!t1) {
+        t1 = proto === null;
+        t1.toString;
+      } else
+        t1 = true;
+      if (t1)
         return A.convertNativeToDart_Dictionary(value);
-      if (Array.isArray(value)) {
+      t1 = Array.isArray(value);
+      t1.toString;
+      if (t1) {
         values = [];
-        for (i = 0; i < value.length; ++i)
+        i = 0;
+        while (true) {
+          t1 = value.length;
+          t1.toString;
+          if (!(i < t1))
+            break;
           values.push(A._convertNativeToDart_Value(value[i]));
+          ++i;
+        }
         return values;
       }
       return value;
     },
     convertNativeToDart_Dictionary(object) {
-      var dict, keys, t1, _i, key;
+      var dict, keys, t1, _i, key, t2;
       if (object == null)
         return null;
       dict = A.LinkedHashMap_LinkedHashMap$_empty(type$.String, type$.dynamic);
       keys = Object.getOwnPropertyNames(object);
       for (t1 = keys.length, _i = 0; _i < keys.length; keys.length === t1 || (0, A.throwConcurrentModificationError)(keys), ++_i) {
         key = keys[_i];
-        dict.$indexSet(0, key, A._convertNativeToDart_Value(object[key]));
+        t2 = key;
+        t2.toString;
+        dict.$indexSet(0, t2, A._convertNativeToDart_Value(object[key]));
       }
       return dict;
     },
-    isJavaScriptSimpleObject(value) {
-      var proto = Object.getPrototypeOf(value);
-      return proto === Object.prototype || proto === null;
-    },
-    _convertDartFunctionFast(f) {
-      var ret,
-        existing = f.$dart_jsFunction;
-      if (existing != null)
-        return existing;
-      ret = function(_call, f) {
-        return function() {
-          return _call(f, Array.prototype.slice.apply(arguments));
-        };
-      }(A._callDartFunctionFast, f);
-      ret[$.$get$DART_CLOSURE_PROPERTY_NAME()] = f;
-      f.$dart_jsFunction = ret;
-      return ret;
-    },
-    _callDartFunctionFast(callback, $arguments) {
-      type$.List_dynamic._as($arguments);
-      type$.Function._as(callback);
-      return A.Primitives_applyFunction(callback, $arguments, null);
-    },
-    allowInterop(f, $F) {
-      if (typeof f == "function")
-        return f;
-      else
-        return $F._as(A._convertDartFunctionFast(f));
-    },
     current() {
       var exception, t1, path, lastIndex, uri = null;
       try {
@@ -7262,7 +7516,7 @@
         return t1;
       }
       $._currentUriBase = uri;
-      if ($.$get$Style_platform() == $.$get$Style_url())
+      if ($.$get$Style_platform() === $.$get$Style_url())
         t1 = $._current = uri.resolve$1(".").toString$0(0);
       else {
         path = uri.toFilePath$0();
@@ -7280,17 +7534,25 @@
       return t1;
     },
     isDriveLetter(path, index) {
-      var t1 = path.length,
+      var t3,
+        t1 = path.length,
         t2 = index + 2;
       if (t1 < t2)
         return false;
-      if (!A.isAlphabetic(B.JSString_methods.codeUnitAt$1(path, index)))
+      if (!(index >= 0 && index < t1))
+        return A.ioore(path, index);
+      if (!A.isAlphabetic(path.charCodeAt(index)))
         return false;
-      if (B.JSString_methods.codeUnitAt$1(path, index + 1) !== 58)
+      t3 = index + 1;
+      if (!(t3 < t1))
+        return A.ioore(path, t3);
+      if (path.charCodeAt(t3) !== 58)
         return false;
       if (t1 === t2)
         return true;
-      return B.JSString_methods.codeUnitAt$1(path, t2) === 47;
+      if (!(t2 >= 0 && t2 < t1))
+        return A.ioore(path, t2);
+      return path.charCodeAt(t2) === 47;
     }
   },
   J = {
@@ -7411,7 +7673,7 @@
     JSString__skipLeadingWhitespace(string, index) {
       var t1, codeUnit;
       for (t1 = string.length; index < t1;) {
-        codeUnit = B.JSString_methods._codeUnitAt$1(string, index);
+        codeUnit = string.charCodeAt(index);
         if (codeUnit !== 32 && codeUnit !== 13 && !J.JSString__isWhitespace(codeUnit))
           break;
         ++index;
@@ -7419,10 +7681,12 @@
       return index;
     },
     JSString__skipTrailingWhitespace(string, index) {
-      var index0, codeUnit;
-      for (; index > 0; index = index0) {
+      var t1, index0, codeUnit;
+      for (t1 = string.length; index > 0; index = index0) {
         index0 = index - 1;
-        codeUnit = B.JSString_methods.codeUnitAt$1(string, index0);
+        if (!(index0 < t1))
+          return A.ioore(string, index0);
+        codeUnit = string.charCodeAt(index0);
         if (codeUnit !== 32 && codeUnit !== 13 && !J.JSString__isWhitespace(codeUnit))
           break;
       }
@@ -7440,7 +7704,7 @@
         return J.JSNull.prototype;
       if (typeof receiver == "boolean")
         return J.JSBool.prototype;
-      if (receiver.constructor == Array)
+      if (Array.isArray(receiver))
         return J.JSArray.prototype;
       if (typeof receiver != "object") {
         if (typeof receiver == "function")
@@ -7456,7 +7720,7 @@
         return J.JSString.prototype;
       if (receiver == null)
         return receiver;
-      if (receiver.constructor == Array)
+      if (Array.isArray(receiver))
         return J.JSArray.prototype;
       if (typeof receiver != "object") {
         if (typeof receiver == "function")
@@ -7470,7 +7734,7 @@
     getInterceptor$ax(receiver) {
       if (receiver == null)
         return receiver;
-      if (receiver.constructor == Array)
+      if (Array.isArray(receiver))
         return J.JSArray.prototype;
       if (typeof receiver != "object") {
         if (typeof receiver == "function")
@@ -7515,6 +7779,9 @@
     get$isEmpty$asx(receiver) {
       return J.getInterceptor$asx(receiver).get$isEmpty(receiver);
     },
+    get$isNotEmpty$asx(receiver) {
+      return J.getInterceptor$asx(receiver).get$isNotEmpty(receiver);
+    },
     get$iterator$ax(receiver) {
       return J.getInterceptor$ax(receiver).get$iterator(receiver);
     },
@@ -7527,6 +7794,9 @@
     get$parent$z(receiver) {
       return J.getInterceptor$z(receiver).get$parent(receiver);
     },
+    get$runtimeType$(receiver) {
+      return J.getInterceptor$(receiver).get$runtimeType(receiver);
+    },
     $eq$(receiver, a0) {
       if (receiver == null)
         return a0 == null;
@@ -7536,7 +7806,7 @@
     },
     $index$asx(receiver, a0) {
       if (typeof a0 === "number")
-        if (receiver.constructor == Array || typeof receiver == "string" || A.isJsIndexable(receiver, receiver[init.dispatchPropertyName]))
+        if (Array.isArray(receiver) || typeof receiver == "string" || A.isJsIndexable(receiver, receiver[init.dispatchPropertyName]))
           if (a0 >>> 0 === a0 && a0 < receiver.length)
             return receiver[a0];
       return J.getInterceptor$asx(receiver).$index(receiver, a0);
@@ -7550,9 +7820,21 @@
     allMatches$2$s(receiver, a0, a1) {
       return J.getInterceptor$s(receiver).allMatches$2(receiver, a0, a1);
     },
+    cancel$0$z(receiver) {
+      return J.getInterceptor$z(receiver).cancel$0(receiver);
+    },
+    cast$1$0$ax(receiver, $T1) {
+      return J.getInterceptor$ax(receiver).cast$1$0(receiver, $T1);
+    },
     codeUnitAt$1$s(receiver, a0) {
       return J.getInterceptor$s(receiver).codeUnitAt$1(receiver, a0);
     },
+    contains$1$asx(receiver, a0) {
+      return J.getInterceptor$asx(receiver).contains$1(receiver, a0);
+    },
+    containsKey$1$x(receiver, a0) {
+      return J.getInterceptor$x(receiver).containsKey$1(receiver, a0);
+    },
     elementAt$1$ax(receiver, a0) {
       return J.getInterceptor$ax(receiver).elementAt$1(receiver, a0);
     },
@@ -7571,6 +7853,12 @@
     noSuchMethod$1$(receiver, a0) {
       return J.getInterceptor$(receiver).noSuchMethod$1(receiver, a0);
     },
+    skip$1$ax(receiver, a0) {
+      return J.getInterceptor$ax(receiver).skip$1(receiver, a0);
+    },
+    toList$0$ax(receiver) {
+      return J.getInterceptor$ax(receiver).toList$0(receiver);
+    },
     toString$0$(receiver) {
       return J.getInterceptor$(receiver).toString$0(receiver);
     },
@@ -7628,8 +7916,10 @@
       return "Instance of '" + A.Primitives_objectTypeName(receiver) + "'";
     },
     noSuchMethod$1(receiver, invocation) {
-      type$.Invocation._as(invocation);
-      throw A.wrapException(A.NoSuchMethodError$(receiver, invocation.get$memberName(), invocation.get$positionalArguments(), invocation.get$namedArguments()));
+      throw A.wrapException(A.NoSuchMethodError_NoSuchMethodError$withInvocation(receiver, type$.Invocation._as(invocation)));
+    },
+    get$runtimeType(receiver) {
+      return A.createRuntimeType(A._instanceTypeFromConstructor(this));
     }
   };
   J.JSBool.prototype = {
@@ -7639,6 +7929,10 @@
     get$hashCode(receiver) {
       return receiver ? 519018 : 218159;
     },
+    get$runtimeType(receiver) {
+      return A.createRuntimeType(type$.bool);
+    },
+    $isTrustedGetRuntimeType: 1,
     $isbool: 1
   };
   J.JSNull.prototype = {
@@ -7651,6 +7945,7 @@
     get$hashCode(receiver) {
       return 0;
     },
+    $isTrustedGetRuntimeType: 1,
     $isNull: 1
   };
   J.JavaScriptObject.prototype = {};
@@ -7674,6 +7969,9 @@
     $isFunction: 1
   };
   J.JSArray.prototype = {
+    cast$1$0(receiver, $R) {
+      return new A.CastList(receiver, A._arrayInstanceType(receiver)._eval$1("@<1>")._bind$1($R)._eval$1("CastList<1,2>"));
+    },
     add$1(receiver, value) {
       A._arrayInstanceType(receiver)._precomputed1._as(value);
       if (!!receiver.fixed$length)
@@ -7700,14 +7998,15 @@
       receiver.splice(index, 0, value);
     },
     insertAll$2(receiver, index, iterable) {
-      var t1, insertionLength, end;
+      var insertionLength, end;
       A._arrayInstanceType(receiver)._eval$1("Iterable<1>")._as(iterable);
       if (!!receiver.fixed$length)
         A.throwExpression(A.UnsupportedError$("insertAll"));
-      t1 = receiver.length;
-      A.RangeError_checkValueInInterval(index, 0, t1, "index");
-      insertionLength = iterable.length;
-      receiver.length = t1 + insertionLength;
+      A.RangeError_checkValueInInterval(index, 0, receiver.length, "index");
+      if (!type$.EfficientLengthIterable_dynamic._is(iterable))
+        iterable = J.toList$0$ax(iterable);
+      insertionLength = J.get$length$asx(iterable);
+      receiver.length = receiver.length + insertionLength;
       end = index + insertionLength;
       this.setRange$4(receiver, end, receiver.length, receiver, index);
       this.setRange$3(receiver, index, end, iterable);
@@ -7761,6 +8060,9 @@
     join$0($receiver) {
       return this.join$1($receiver, "");
     },
+    skip$1(receiver, n) {
+      return A.SubListIterable$(receiver, n, null, A._arrayInstanceType(receiver)._precomputed1);
+    },
     fold$1$2(receiver, initialValue, combine, $T) {
       var $length, value, i;
       $T._as(initialValue);
@@ -7790,7 +8092,7 @@
       throw A.wrapException(A.IterableElementError_noElement());
     },
     setRange$4(receiver, start, end, iterable, skipCount) {
-      var $length, otherList, t1, i;
+      var $length, otherList, otherStart, t1, i;
       A._arrayInstanceType(receiver)._eval$1("Iterable<1>")._as(iterable);
       if (!!receiver.immutable$list)
         A.throwExpression(A.UnsupportedError$("setRange"));
@@ -7799,20 +8101,33 @@
       if ($length === 0)
         return;
       A.RangeError_checkNotNegative(skipCount, "skipCount");
-      otherList = iterable;
+      if (type$.List_dynamic._is(iterable)) {
+        otherList = iterable;
+        otherStart = skipCount;
+      } else {
+        otherList = J.skip$1$ax(iterable, skipCount).toList$1$growable(0, false);
+        otherStart = 0;
+      }
       t1 = J.getInterceptor$asx(otherList);
-      if (skipCount + $length > t1.get$length(otherList))
+      if (otherStart + $length > t1.get$length(otherList))
         throw A.wrapException(A.IterableElementError_tooFew());
-      if (skipCount < start)
+      if (otherStart < start)
         for (i = $length - 1; i >= 0; --i)
-          receiver[start + i] = t1.$index(otherList, skipCount + i);
+          receiver[start + i] = t1.$index(otherList, otherStart + i);
       else
         for (i = 0; i < $length; ++i)
-          receiver[start + i] = t1.$index(otherList, skipCount + i);
+          receiver[start + i] = t1.$index(otherList, otherStart + i);
     },
     setRange$3($receiver, start, end, iterable) {
       return this.setRange$4($receiver, start, end, iterable, 0);
     },
+    contains$1(receiver, other) {
+      var i;
+      for (i = 0; i < receiver.length; ++i)
+        if (J.$eq$(receiver[i], other))
+          return true;
+      return false;
+    },
     get$isEmpty(receiver) {
       return receiver.length === 0;
     },
@@ -7820,7 +8135,14 @@
       return receiver.length !== 0;
     },
     toString$0(receiver) {
-      return A.IterableBase_iterableToFullString(receiver, "[", "]");
+      return A.Iterable_iterableToFullString(receiver, "[", "]");
+    },
+    toList$1$growable(receiver, growable) {
+      var t1 = A._setArrayType(receiver.slice(0), A._arrayInstanceType(receiver));
+      return t1;
+    },
+    toList$0($receiver) {
+      return this.toList$1$growable($receiver, true);
     },
     get$iterator(receiver) {
       return new J.ArrayIterator(receiver, receiver.length, A._arrayInstanceType(receiver)._eval$1("ArrayIterator<1>"));
@@ -7838,7 +8160,6 @@
       return receiver[index];
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       A._arrayInstanceType(receiver)._precomputed1._as(value);
       if (!!receiver.immutable$list)
         A.throwExpression(A.UnsupportedError$("indexed set"));
@@ -7860,8 +8181,10 @@
       var t2, _this = this,
         t1 = _this._iterable,
         $length = t1.length;
-      if (_this.__interceptors$_length !== $length)
-        throw A.wrapException(A.throwConcurrentModificationError(t1));
+      if (_this.__interceptors$_length !== $length) {
+        t1 = A.throwConcurrentModificationError(t1);
+        throw A.wrapException(t1);
+      }
       t2 = _this._index;
       if (t2 >= $length) {
         _this.set$_current(null);
@@ -7877,6 +8200,16 @@
     $isIterator: 1
   };
   J.JSNumber.prototype = {
+    toInt$0(receiver) {
+      var t1;
+      if (receiver >= -2147483648 && receiver <= 2147483647)
+        return receiver | 0;
+      if (isFinite(receiver)) {
+        t1 = receiver < 0 ? Math.ceil(receiver) : Math.floor(receiver);
+        return t1 + 0;
+      }
+      throw A.wrapException(A.UnsupportedError$("" + receiver + ".toInt()"));
+    },
     toString$0(receiver) {
       if (receiver === 0 && 1 / receiver < 0)
         return "-0.0";
@@ -7940,11 +8273,25 @@
     _shrBothPositive$1(receiver, other) {
       return other > 31 ? 0 : receiver >>> other;
     },
+    get$runtimeType(receiver) {
+      return A.createRuntimeType(type$.num);
+    },
     $isdouble: 1,
     $isnum: 1
   };
-  J.JSInt.prototype = {$isint: 1};
-  J.JSNumNotInt.prototype = {};
+  J.JSInt.prototype = {
+    get$runtimeType(receiver) {
+      return A.createRuntimeType(type$.int);
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isint: 1
+  };
+  J.JSNumNotInt.prototype = {
+    get$runtimeType(receiver) {
+      return A.createRuntimeType(type$.double);
+    },
+    $isTrustedGetRuntimeType: 1
+  };
   J.JSString.prototype = {
     codeUnitAt$1(receiver, index) {
       if (index < 0)
@@ -7953,11 +8300,6 @@
         A.throwExpression(A.diagnoseIndexError(receiver, index));
       return receiver.charCodeAt(index);
     },
-    _codeUnitAt$1(receiver, index) {
-      if (index >= receiver.length)
-        throw A.wrapException(A.diagnoseIndexError(receiver, index));
-      return receiver.charCodeAt(index);
-    },
     allMatches$2(receiver, string, start) {
       var t1 = string.length;
       if (start > t1)
@@ -7968,15 +8310,20 @@
       return this.allMatches$2($receiver, string, 0);
     },
     matchAsPrefix$2(receiver, string, start) {
-      var t1, i, _null = null;
+      var t1, t2, i, t3, _null = null;
       if (start < 0 || start > string.length)
         throw A.wrapException(A.RangeError$range(start, 0, string.length, _null, _null));
       t1 = receiver.length;
-      if (start + t1 > string.length)
+      t2 = string.length;
+      if (start + t1 > t2)
         return _null;
-      for (i = 0; i < t1; ++i)
-        if (this.codeUnitAt$1(string, start + i) !== this._codeUnitAt$1(receiver, i))
+      for (i = 0; i < t1; ++i) {
+        t3 = start + i;
+        if (!(t3 >= 0 && t3 < t2))
+          return A.ioore(string, t3);
+        if (string.charCodeAt(t3) !== receiver.charCodeAt(i))
           return _null;
+      }
       return new A.StringMatch(start, receiver);
     },
     $add(receiver, other) {
@@ -7990,12 +8337,10 @@
       return other === this.substring$1(receiver, t1 - otherLength);
     },
     replaceFirst$2(receiver, from, to) {
-      type$.Pattern._as(from);
       A.RangeError_checkValueInInterval(0, 0, receiver.length, "startIndex");
       return A.stringReplaceFirstUnchecked(receiver, from, to, 0);
     },
     split$1(receiver, pattern) {
-      type$.Pattern._as(pattern);
       if (typeof pattern == "string")
         return A._setArrayType(receiver.split(pattern), type$.JSArray_String);
       else if (pattern instanceof A.JSSyntaxRegExp && pattern.get$_nativeAnchoredVersion().exec("").length - 2 === 0)
@@ -8026,7 +8371,6 @@
     },
     startsWith$2(receiver, pattern, index) {
       var endIndex;
-      type$.Pattern._as(pattern);
       if (index < 0 || index > receiver.length)
         throw A.wrapException(A.RangeError$range(index, 0, receiver.length, null, null));
       if (typeof pattern == "string") {
@@ -8052,14 +8396,18 @@
         endIndex = result.length;
       if (endIndex === 0)
         return result;
-      if (this._codeUnitAt$1(result, 0) === 133) {
+      if (0 >= endIndex)
+        return A.ioore(result, 0);
+      if (result.charCodeAt(0) === 133) {
         startIndex = J.JSString__skipLeadingWhitespace(result, 1);
         if (startIndex === endIndex)
           return "";
       } else
         startIndex = 0;
       t1 = endIndex - 1;
-      endIndex0 = this.codeUnitAt$1(result, t1) === 133 ? J.JSString__skipTrailingWhitespace(result, t1) : endIndex;
+      if (!(t1 >= 0))
+        return A.ioore(result, t1);
+      endIndex0 = result.charCodeAt(t1) === 133 ? J.JSString__skipTrailingWhitespace(result, t1) : endIndex;
       if (startIndex === 0 && endIndex0 === endIndex)
         return result;
       return result.substring(startIndex, endIndex0);
@@ -8119,16 +8467,8 @@
     lastIndexOf$1($receiver, pattern) {
       return this.lastIndexOf$2($receiver, pattern, null);
     },
-    contains$2(receiver, other, startIndex) {
-      var t1;
-      type$.Pattern._as(other);
-      t1 = receiver.length;
-      if (startIndex > t1)
-        throw A.wrapException(A.RangeError$range(startIndex, 0, t1, null, null));
-      return A.stringContainsUnchecked(receiver, other, startIndex);
-    },
-    contains$1($receiver, other) {
-      return this.contains$2($receiver, other, 0);
+    contains$1(receiver, other) {
+      return A.stringContainsUnchecked(receiver, other, 0);
     },
     toString$0(receiver) {
       return receiver;
@@ -8144,6 +8484,9 @@
       hash ^= hash >> 11;
       return hash + ((hash & 16383) << 15) & 536870911;
     },
+    get$runtimeType(receiver) {
+      return A.createRuntimeType(type$.String);
+    },
     get$length(receiver) {
       return receiver.length;
     },
@@ -8153,6 +8496,7 @@
         throw A.wrapException(A.diagnoseIndexError(receiver, index));
       return receiver[index];
     },
+    $isTrustedGetRuntimeType: 1,
     $isPattern: 1,
     $isString: 1
   };
@@ -8232,6 +8576,66 @@
     },
     $isStreamSubscription: 1
   };
+  A._CastIterableBase.prototype = {
+    get$iterator(_) {
+      var t1 = A._instanceType(this);
+      return new A.CastIterator(J.get$iterator$ax(this.get$_source()), t1._eval$1("@<1>")._bind$1(t1._rest[1])._eval$1("CastIterator<1,2>"));
+    },
+    get$length(_) {
+      return J.get$length$asx(this.get$_source());
+    },
+    get$isEmpty(_) {
+      return J.get$isEmpty$asx(this.get$_source());
+    },
+    get$isNotEmpty(_) {
+      return J.get$isNotEmpty$asx(this.get$_source());
+    },
+    skip$1(_, count) {
+      var t1 = A._instanceType(this);
+      return A.CastIterable_CastIterable(J.skip$1$ax(this.get$_source(), count), t1._precomputed1, t1._rest[1]);
+    },
+    elementAt$1(_, index) {
+      return A._instanceType(this)._rest[1]._as(J.elementAt$1$ax(this.get$_source(), index));
+    },
+    toString$0(_) {
+      return J.toString$0$(this.get$_source());
+    }
+  };
+  A.CastIterator.prototype = {
+    moveNext$0() {
+      return this._source.moveNext$0();
+    },
+    get$current(_) {
+      var t1 = this._source;
+      return this.$ti._rest[1]._as(t1.get$current(t1));
+    },
+    $isIterator: 1
+  };
+  A.CastIterable.prototype = {
+    get$_source() {
+      return this._source;
+    }
+  };
+  A._EfficientLengthCastIterable.prototype = {$isEfficientLengthIterable: 1};
+  A._CastListBase.prototype = {
+    $index(_, index) {
+      return this.$ti._rest[1]._as(J.$index$asx(this._source, A._asInt(index)));
+    },
+    $indexSet(_, index, value) {
+      var t1 = this.$ti;
+      J.$indexSet$ax(this._source, index, t1._precomputed1._as(t1._rest[1]._as(value)));
+    },
+    $isEfficientLengthIterable: 1,
+    $isList: 1
+  };
+  A.CastList.prototype = {
+    cast$1$0(_, $R) {
+      return new A.CastList(this._source, this.$ti._eval$1("@<1>")._bind$1($R)._eval$1("CastList<1,2>"));
+    },
+    get$_source() {
+      return this._source;
+    }
+  };
   A.LateError.prototype = {
     toString$0(_) {
       return "LateInitializationError: " + this._message;
@@ -8242,14 +8646,19 @@
       return this._string.length;
     },
     $index(_, i) {
-      return B.JSString_methods.codeUnitAt$1(this._string, A._asInt(i));
+      var t1;
+      A._asInt(i);
+      t1 = this._string;
+      if (!(i >= 0 && i < t1.length))
+        return A.ioore(t1, i);
+      return t1.charCodeAt(i);
     }
   };
   A.nullFuture_closure.prototype = {
     call$0() {
       return A.Future_Future$value(null, type$.Null);
     },
-    $signature: 44
+    $signature: 61
   };
   A.SentinelValue.prototype = {};
   A.EfficientLengthIterable.prototype = {};
@@ -8303,12 +8712,15 @@
           throw A.wrapException(A.ConcurrentModificationError$(_this));
       }
       return value;
+    },
+    skip$1(_, count) {
+      return A.SubListIterable$(this, count, null, A._instanceType(this)._eval$1("ListIterable.E"));
     }
   };
   A.SubListIterable.prototype = {
     SubListIterable$3(_iterable, _start, _endOrLength, $E) {
       var endOrLength,
-        t1 = this.__internal$_start;
+        t1 = this._start;
       A.RangeError_checkNotNegative(t1, "start");
       endOrLength = this._endOrLength;
       if (endOrLength != null) {
@@ -8326,7 +8738,7 @@
     },
     get$_startIndex() {
       var $length = J.get$length$asx(this.__internal$_iterable),
-        t1 = this.__internal$_start;
+        t1 = this._start;
       if (t1 > $length)
         return $length;
       return t1;
@@ -8334,7 +8746,7 @@
     get$length(_) {
       var endOrLength,
         $length = J.get$length$asx(this.__internal$_iterable),
-        t1 = this.__internal$_start;
+        t1 = this._start;
       if (t1 >= $length)
         return 0;
       endOrLength = this._endOrLength;
@@ -8348,8 +8760,39 @@
       var _this = this,
         realIndex = _this.get$_startIndex() + index;
       if (index < 0 || realIndex >= _this.get$_endIndex())
-        throw A.wrapException(A.IndexError$(index, _this, "index", null, null));
+        throw A.wrapException(A.IndexError$withLength(index, _this.get$length(_this), _this, "index"));
       return J.elementAt$1$ax(_this.__internal$_iterable, realIndex);
+    },
+    skip$1(_, count) {
+      var newStart, endOrLength, _this = this;
+      A.RangeError_checkNotNegative(count, "count");
+      newStart = _this._start + count;
+      endOrLength = _this._endOrLength;
+      if (endOrLength != null && newStart >= endOrLength)
+        return new A.EmptyIterable(_this.$ti._eval$1("EmptyIterable<1>"));
+      return A.SubListIterable$(_this.__internal$_iterable, newStart, endOrLength, _this.$ti._precomputed1);
+    },
+    toList$1$growable(_, growable) {
+      var $length, result, i, _this = this,
+        start = _this._start,
+        t1 = _this.__internal$_iterable,
+        t2 = J.getInterceptor$asx(t1),
+        end = t2.get$length(t1),
+        endOrLength = _this._endOrLength;
+      if (endOrLength != null && endOrLength < end)
+        end = endOrLength;
+      $length = end - start;
+      if ($length <= 0) {
+        t1 = J.JSArray_JSArray$fixed(0, _this.$ti._precomputed1);
+        return t1;
+      }
+      result = A.List_List$filled($length, t2.elementAt$1(t1, start), false, _this.$ti._precomputed1);
+      for (i = 1; i < $length; ++i) {
+        B.JSArray_methods.$indexSet(result, i, t2.elementAt$1(t1, start + i));
+        if (t2.get$length(t1) < end)
+          throw A.wrapException(A.ConcurrentModificationError$(_this));
+      }
+      return result;
     }
   };
   A.ListIterator.prototype = {
@@ -8385,6 +8828,12 @@
     },
     get$length(_) {
       return J.get$length$asx(this.__internal$_iterable);
+    },
+    get$isEmpty(_) {
+      return J.get$isEmpty$asx(this.__internal$_iterable);
+    },
+    elementAt$1(_, index) {
+      return this._f.call$1(J.elementAt$1$ax(this.__internal$_iterable, index));
     }
   };
   A.EfficientLengthMappedIterable.prototype = {$isEfficientLengthIterable: 1};
@@ -8405,7 +8854,8 @@
     },
     set$__internal$_current(_current) {
       this.__internal$_current = this.$ti._eval$1("2?")._as(_current);
-    }
+    },
+    $isIterator: 1
   };
   A.MappedListIterable.prototype = {
     get$length(_) {
@@ -8435,7 +8885,8 @@
     get$current(_) {
       var t1 = this._iterator;
       return t1.get$current(t1);
-    }
+    },
+    $isIterator: 1
   };
   A.ExpandIterable.prototype = {
     get$iterator(_) {
@@ -8502,8 +8953,47 @@
       }
       t1 = this._iterator;
       return t1.get$current(t1);
+    },
+    $isIterator: 1
+  };
+  A.SkipIterable.prototype = {
+    skip$1(_, count) {
+      A.ArgumentError_checkNotNull(count, "count", type$.int);
+      A.RangeError_checkNotNegative(count, "count");
+      return new A.SkipIterable(this.__internal$_iterable, this._skipCount + count, A._instanceType(this)._eval$1("SkipIterable<1>"));
+    },
+    get$iterator(_) {
+      return new A.SkipIterator(J.get$iterator$ax(this.__internal$_iterable), this._skipCount, A._instanceType(this)._eval$1("SkipIterator<1>"));
     }
   };
+  A.EfficientLengthSkipIterable.prototype = {
+    get$length(_) {
+      var $length = J.get$length$asx(this.__internal$_iterable) - this._skipCount;
+      if ($length >= 0)
+        return $length;
+      return 0;
+    },
+    skip$1(_, count) {
+      A.ArgumentError_checkNotNull(count, "count", type$.int);
+      A.RangeError_checkNotNegative(count, "count");
+      return new A.EfficientLengthSkipIterable(this.__internal$_iterable, this._skipCount + count, this.$ti);
+    },
+    $isEfficientLengthIterable: 1
+  };
+  A.SkipIterator.prototype = {
+    moveNext$0() {
+      var t1, i;
+      for (t1 = this._iterator, i = 0; i < this._skipCount; ++i)
+        t1.moveNext$0();
+      this._skipCount = 0;
+      return t1.moveNext$0();
+    },
+    get$current(_) {
+      var t1 = this._iterator;
+      return t1.get$current(t1);
+    },
+    $isIterator: 1
+  };
   A.SkipWhileIterable.prototype = {
     get$iterator(_) {
       return new A.SkipWhileIterator(J.get$iterator$ax(this.__internal$_iterable), this._f, this.$ti._eval$1("SkipWhileIterator<1>"));
@@ -8523,6 +9013,29 @@
     get$current(_) {
       var t1 = this._iterator;
       return t1.get$current(t1);
+    },
+    $isIterator: 1
+  };
+  A.EmptyIterable.prototype = {
+    get$iterator(_) {
+      return B.C_EmptyIterator;
+    },
+    get$isEmpty(_) {
+      return true;
+    },
+    get$length(_) {
+      return 0;
+    },
+    elementAt$1(_, index) {
+      throw A.wrapException(A.RangeError$range(index, 0, 0, "index", null));
+    },
+    map$1$1(_, toElement, $T) {
+      this.$ti._bind$1($T)._eval$1("1(2)")._as(toElement);
+      return new A.EmptyIterable($T._eval$1("EmptyIterable<0>"));
+    },
+    skip$1(_, count) {
+      A.RangeError_checkNotNegative(count, "count");
+      return this;
     }
   };
   A.EmptyIterator.prototype = {
@@ -8556,7 +9069,6 @@
   A.FixedLengthListMixin.prototype = {};
   A.UnmodifiableListMixin.prototype = {
     $indexSet(_, index, value) {
-      A._asInt(index);
       A._instanceType(this)._eval$1("UnmodifiableListMixin.E")._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot modify an unmodifiable list"));
     }
@@ -8577,20 +9089,21 @@
       var hash = this._hashCode;
       if (hash != null)
         return hash;
-      hash = 664597 * J.get$hashCode$(this._name) & 536870911;
+      hash = 664597 * B.JSString_methods.get$hashCode(this._name) & 536870911;
       this._hashCode = hash;
       return hash;
     },
     toString$0(_) {
-      return 'Symbol("' + A.S(this._name) + '")';
+      return 'Symbol("' + this._name + '")';
     },
     $eq(_, other) {
       if (other == null)
         return false;
-      return other instanceof A.Symbol && this._name == other._name;
+      return other instanceof A.Symbol && this._name === other._name;
     },
     $isSymbol0: 1
   };
+  A.__CastListBase__CastIterableBase_ListMixin.prototype = {};
   A.ConstantMapView.prototype = {};
   A.ConstantMap.prototype = {
     get$isEmpty(_) {
@@ -8599,61 +9112,94 @@
     toString$0(_) {
       return A.MapBase_mapToString(this);
     },
-    $indexSet(_, key, val) {
+    $indexSet(_, key, value) {
       var t1 = A._instanceType(this);
       t1._precomputed1._as(key);
-      t1._rest[1]._as(val);
+      t1._rest[1]._as(value);
       A.ConstantMap__throwUnmodifiable();
     },
     $isMap: 1
   };
   A.ConstantStringMap.prototype = {
     get$length(_) {
-      return this._length;
+      return this._values.length;
+    },
+    get$__js_helper$_keys() {
+      var keys = this.$keys;
+      if (keys == null) {
+        keys = Object.keys(this._jsIndex);
+        this.$keys = keys;
+      }
+      return keys;
     },
     containsKey$1(_, key) {
       if (typeof key != "string")
         return false;
       if ("__proto__" === key)
         return false;
-      return this._jsObject.hasOwnProperty(key);
+      return this._jsIndex.hasOwnProperty(key);
     },
     $index(_, key) {
       if (!this.containsKey$1(0, key))
         return null;
-      return this._jsObject[A._asString(key)];
+      return this._values[this._jsIndex[key]];
     },
     forEach$1(_, f) {
-      var keys, t2, t3, i, t4,
-        t1 = this.$ti;
-      t1._eval$1("~(1,2)")._as(f);
-      keys = this.__js_helper$_keys;
-      for (t2 = keys.length, t3 = this._jsObject, t1 = t1._rest[1], i = 0; i < t2; ++i) {
-        t4 = A._asString(keys[i]);
-        f.call$2(t4, t1._as(t3[t4]));
-      }
+      var keys, values, t1, i;
+      this.$ti._eval$1("~(1,2)")._as(f);
+      keys = this.get$__js_helper$_keys();
+      values = this._values;
+      for (t1 = keys.length, i = 0; i < t1; ++i)
+        f.call$2(keys[i], values[i]);
     },
     get$keys(_) {
-      return new A._ConstantMapKeyIterable(this, this.$ti._eval$1("_ConstantMapKeyIterable<1>"));
+      return new A._KeysOrValues(this.get$__js_helper$_keys(), this.$ti._eval$1("_KeysOrValues<1>"));
     }
   };
-  A._ConstantMapKeyIterable.prototype = {
-    get$iterator(_) {
-      var t1 = this._map.__js_helper$_keys;
-      return new J.ArrayIterator(t1, t1.length, A._arrayInstanceType(t1)._eval$1("ArrayIterator<1>"));
-    },
+  A._KeysOrValues.prototype = {
     get$length(_) {
-      return this._map.__js_helper$_keys.length;
+      return this._elements.length;
+    },
+    get$isEmpty(_) {
+      return 0 === this._elements.length;
+    },
+    get$isNotEmpty(_) {
+      return 0 !== this._elements.length;
+    },
+    get$iterator(_) {
+      var t1 = this._elements;
+      return new A._KeysOrValuesOrElementsIterator(t1, t1.length, this.$ti._eval$1("_KeysOrValuesOrElementsIterator<1>"));
     }
   };
+  A._KeysOrValuesOrElementsIterator.prototype = {
+    get$current(_) {
+      var t1 = this.__js_helper$_current;
+      return t1 == null ? this.$ti._precomputed1._as(t1) : t1;
+    },
+    moveNext$0() {
+      var _this = this,
+        t1 = _this.__js_helper$_index;
+      if (t1 >= _this._length) {
+        _this.set$__js_helper$_current(null);
+        return false;
+      }
+      _this.set$__js_helper$_current(_this._elements[t1]);
+      ++_this.__js_helper$_index;
+      return true;
+    },
+    set$__js_helper$_current(_current) {
+      this.__js_helper$_current = this.$ti._eval$1("1?")._as(_current);
+    },
+    $isIterator: 1
+  };
   A.Instantiation.prototype = {
     $eq(_, other) {
       if (other == null)
         return false;
-      return other instanceof A.Instantiation && this._genericClosure.$eq(0, other._genericClosure) && A.getRuntimeType(this) === A.getRuntimeType(other);
+      return other instanceof A.Instantiation1 && this._genericClosure.$eq(0, other._genericClosure) && A.getRuntimeTypeOfClosure(this) === A.getRuntimeTypeOfClosure(other);
     },
     get$hashCode(_) {
-      return A.Object_hash(this._genericClosure, A.getRuntimeType(this), B.C_SentinelValue, B.C_SentinelValue);
+      return A.Object_hash(this._genericClosure, A.getRuntimeTypeOfClosure(this), B.C_SentinelValue, B.C_SentinelValue);
     },
     toString$0(_) {
       var t1 = B.JSArray_methods.join$1([A.createRuntimeType(this.$ti._precomputed1)], ", ");
@@ -8726,7 +9272,7 @@
       B.JSArray_methods.add$1(this.$arguments, argument);
       ++t1.argumentCount;
     },
-    $signature: 5
+    $signature: 3
   };
   A.TypeErrorDecoder.prototype = {
     matchTypeError$1(message) {
@@ -8786,7 +9332,6 @@
     },
     $isException: 1
   };
-  A.ExceptionAndStackTrace.prototype = {};
   A._StackTrace.prototype = {
     toString$0(_) {
       var trace,
@@ -8841,6 +9386,11 @@
       return "Closure '" + this.$_name + "' of " + ("Instance of '" + A.Primitives_objectTypeName(this._receiver) + "'");
     }
   };
+  A._CyclicInitializationError.prototype = {
+    toString$0(_) {
+      return "Reading static variable '" + this.variableName + "' during its initialization";
+    }
+  };
   A.RuntimeError.prototype = {
     toString$0(_) {
       return "RuntimeError: " + this.message;
@@ -8918,7 +9468,7 @@
       return bucket[index].hashMapCellValue;
     },
     $indexSet(_, key, value) {
-      var strings, nums, _this = this,
+      var strings, nums, rest, hash, bucket, index, _this = this,
         t1 = A._instanceType(_this);
       t1._precomputed1._as(key);
       t1._rest[1]._as(value);
@@ -8928,27 +9478,21 @@
       } else if (typeof key == "number" && (key & 0x3fffffff) === key) {
         nums = _this._nums;
         _this._addHashTableEntry$3(nums == null ? _this._nums = _this._newHashTable$0() : nums, key, value);
-      } else
-        _this.internalSet$2(key, value);
-    },
-    internalSet$2(key, value) {
-      var rest, hash, bucket, index, _this = this,
-        t1 = A._instanceType(_this);
-      t1._precomputed1._as(key);
-      t1._rest[1]._as(value);
-      rest = _this.__js_helper$_rest;
-      if (rest == null)
-        rest = _this.__js_helper$_rest = _this._newHashTable$0();
-      hash = _this.internalComputeHashCode$1(key);
-      bucket = rest[hash];
-      if (bucket == null)
-        rest[hash] = [_this._newLinkedCell$2(key, value)];
-      else {
-        index = _this.internalFindBucketIndex$2(bucket, key);
-        if (index >= 0)
-          bucket[index].hashMapCellValue = value;
-        else
-          bucket.push(_this._newLinkedCell$2(key, value));
+      } else {
+        rest = _this.__js_helper$_rest;
+        if (rest == null)
+          rest = _this.__js_helper$_rest = _this._newHashTable$0();
+        hash = _this.internalComputeHashCode$1(key);
+        bucket = rest[hash];
+        if (bucket == null)
+          rest[hash] = [_this._newLinkedCell$2(key, value)];
+        else {
+          index = _this.internalFindBucketIndex$2(bucket, key);
+          if (index >= 0)
+            bucket[index].hashMapCellValue = value;
+          else
+            bucket.push(_this._newLinkedCell$2(key, value));
+        }
       }
     },
     putIfAbsent$2(_, key, ifAbsent) {
@@ -9066,7 +9610,7 @@
       _this._modified$0();
     },
     internalComputeHashCode$1(key) {
-      return J.get$hashCode$(key) & 0x3fffffff;
+      return J.get$hashCode$(key) & 1073741823;
     },
     internalFindBucketIndex$2(bucket, key) {
       var $length, i;
@@ -9113,6 +9657,9 @@
         t2 = new A.LinkedHashMapKeyIterator(t1, t1._modifications, this.$ti._eval$1("LinkedHashMapKeyIterator<1>"));
       t2._cell = t1._first;
       return t2;
+    },
+    contains$1(_, element) {
+      return this._map.containsKey$1(0, element);
     }
   };
   A.LinkedHashMapKeyIterator.prototype = {
@@ -9143,19 +9690,19 @@
     call$1(o) {
       return this.getTag(o);
     },
-    $signature: 14
+    $signature: 15
   };
   A.initHooks_closure0.prototype = {
     call$2(o, tag) {
       return this.getUnknownTag(o, tag);
     },
-    $signature: 42
+    $signature: 36
   };
   A.initHooks_closure1.prototype = {
     call$1(tag) {
       return this.prototypeForTag(A._asString(tag));
     },
-    $signature: 50
+    $signature: 37
   };
   A.JSSyntaxRegExp.prototype = {
     toString$0(_) {
@@ -9223,7 +9770,8 @@
         throw A.wrapException(A.RangeError$range(start, 0, string.length, null, null));
       return this._execAnchored$2(string, start);
     },
-    $isPattern: 1
+    $isPattern: 1,
+    $isRegExp: 1
   };
   A._MatchImplementation.prototype = {
     get$start(_) {
@@ -9246,7 +9794,7 @@
   };
   A._AllMatchesIterable.prototype = {
     get$iterator(_) {
-      return new A._AllMatchesIterator(this._re, this.__js_helper$_string, this._start);
+      return new A._AllMatchesIterator(this._re, this.__js_helper$_string, this.__js_helper$_start);
     }
   };
   A._AllMatchesIterator.prototype = {
@@ -9272,9 +9820,13 @@
               t1 = _this._nextIndex;
               t3 = t1 + 1;
               if (t3 < t2) {
-                t1 = B.JSString_methods.codeUnitAt$1(string, t1);
+                if (!(t1 >= 0 && t1 < t2))
+                  return A.ioore(string, t1);
+                t1 = string.charCodeAt(t1);
                 if (t1 >= 55296 && t1 <= 56319) {
-                  t1 = B.JSString_methods.codeUnitAt$1(string, t3);
+                  if (!(t3 >= 0))
+                    return A.ioore(string, t3);
+                  t1 = string.charCodeAt(t3);
                   t1 = t1 >= 56320 && t1 <= 57343;
                 } else
                   t1 = false;
@@ -9343,13 +9895,41 @@
   };
   A._Cell.prototype = {
     _readLocal$0() {
-      var t1 = this.__late_helper$_value;
+      var t1 = this._value;
       if (t1 === this)
         throw A.wrapException(new A.LateError("Local '" + this.__late_helper$_name + "' has not been initialized."));
       return t1;
     }
   };
+  A._InitializedCell.prototype = {
+    _readFinal$0() {
+      var result, _this = this,
+        t1 = _this._value;
+      if (t1 === _this) {
+        result = _this._initializer.call$0();
+        if (_this._value !== _this)
+          throw A.wrapException(new A.LateError("Local '" + _this.__late_helper$_name + string$.x27_has_));
+        _this._value = result;
+        t1 = result;
+      }
+      return t1;
+    }
+  };
+  A.NativeByteBuffer.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_ByteBuffer_RkP;
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isByteBuffer: 1
+  };
   A.NativeTypedData.prototype = {};
+  A.NativeByteData.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_ByteData_zNC;
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isByteData: 1
+  };
   A.NativeTypedArray.prototype = {
     get$length(receiver) {
       return receiver.length;
@@ -9363,7 +9943,6 @@
       return receiver[index];
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       A._asDouble(value);
       A._checkValidIndex(index, receiver, receiver.length);
       receiver[index] = value;
@@ -9374,7 +9953,6 @@
   };
   A.NativeTypedArrayOfInt.prototype = {
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       A._asInt(value);
       A._checkValidIndex(index, receiver, receiver.length);
       receiver[index] = value;
@@ -9383,42 +9961,84 @@
     $isIterable: 1,
     $isList: 1
   };
+  A.NativeFloat32List.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_Float32List_LB7;
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isFloat32List: 1
+  };
+  A.NativeFloat64List.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_Float64List_LB7;
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isFloat64List: 1
+  };
   A.NativeInt16List.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_Int16List_uXf;
+    },
     $index(receiver, index) {
       A._asInt(index);
       A._checkValidIndex(index, receiver, receiver.length);
       return receiver[index];
-    }
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isInt16List: 1
   };
   A.NativeInt32List.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_Int32List_O50;
+    },
     $index(receiver, index) {
       A._asInt(index);
       A._checkValidIndex(index, receiver, receiver.length);
       return receiver[index];
-    }
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isInt32List: 1
   };
   A.NativeInt8List.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_Int8List_ekJ;
+    },
     $index(receiver, index) {
       A._asInt(index);
       A._checkValidIndex(index, receiver, receiver.length);
       return receiver[index];
-    }
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isInt8List: 1
   };
   A.NativeUint16List.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_Uint16List_2bx;
+    },
     $index(receiver, index) {
       A._asInt(index);
       A._checkValidIndex(index, receiver, receiver.length);
       return receiver[index];
-    }
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isUint16List: 1
   };
   A.NativeUint32List.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_Uint32List_2bx;
+    },
     $index(receiver, index) {
       A._asInt(index);
       A._checkValidIndex(index, receiver, receiver.length);
       return receiver[index];
-    }
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isUint32List: 1
   };
   A.NativeUint8ClampedList.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_Uint8ClampedList_Jik;
+    },
     get$length(receiver) {
       return receiver.length;
     },
@@ -9426,9 +10046,14 @@
       A._asInt(index);
       A._checkValidIndex(index, receiver, receiver.length);
       return receiver[index];
-    }
+    },
+    $isTrustedGetRuntimeType: 1,
+    $isUint8ClampedList: 1
   };
   A.NativeUint8List.prototype = {
+    get$runtimeType(receiver) {
+      return B.Type_Uint8List_WLA;
+    },
     get$length(receiver) {
       return receiver.length;
     },
@@ -9440,6 +10065,7 @@
     sublist$2(receiver, start, end) {
       return new Uint8Array(receiver.subarray(start, A._checkValidRange(start, end, receiver.length)));
     },
+    $isTrustedGetRuntimeType: 1,
     $isNativeUint8List: 1,
     $isUint8List: 1
   };
@@ -9474,7 +10100,7 @@
       t1.storedCallback = null;
       f.call$0();
     },
-    $signature: 8
+    $signature: 10
   };
   A._AsyncRun__initializeScheduleImmediate_closure.prototype = {
     call$1(callback) {
@@ -9484,7 +10110,7 @@
       t2 = this.span;
       t1.firstChild ? t1.removeChild(t2) : t1.appendChild(t2);
     },
-    $signature: 48
+    $signature: 30
   };
   A._AsyncRun__scheduleImmediateJsOverride_internalCallback.prototype = {
     call$0() {
@@ -9536,50 +10162,6 @@
     },
     $signature: 2
   };
-  A._AsyncAwaitCompleter.prototype = {
-    complete$1(_, value) {
-      var t2, _this = this,
-        t1 = _this.$ti;
-      t1._eval$1("1/?")._as(value);
-      if (value == null)
-        t1._precomputed1._as(value);
-      if (!_this.isSync)
-        _this._future._asyncComplete$1(value);
-      else {
-        t2 = _this._future;
-        if (t1._eval$1("Future<1>")._is(value))
-          t2._chainFuture$1(value);
-        else
-          t2._completeWithValue$1(t1._precomputed1._as(value));
-      }
-    },
-    completeError$2(e, st) {
-      var t1 = this._future;
-      if (this.isSync)
-        t1._completeError$2(e, st);
-      else
-        t1._asyncCompleteError$2(e, st);
-    },
-    $isCompleter: 1
-  };
-  A._awaitOnObject_closure.prototype = {
-    call$1(result) {
-      return this.bodyFunction.call$2(0, result);
-    },
-    $signature: 3
-  };
-  A._awaitOnObject_closure0.prototype = {
-    call$2(error, stackTrace) {
-      this.bodyFunction.call$2(1, new A.ExceptionAndStackTrace(error, type$.StackTrace._as(stackTrace)));
-    },
-    $signature: 65
-  };
-  A._wrapJsFunctionForAsync_closure.prototype = {
-    call$2(errorCode, result) {
-      this.$protected(A._asInt(errorCode), result);
-    },
-    $signature: 40
-  };
   A.AsyncError.prototype = {
     toString$0(_) {
       return A.S(this.error);
@@ -9674,6 +10256,10 @@
     }
   };
   A._Future.prototype = {
+    _setChained$1(source) {
+      this._async$_state = this._async$_state & 1 | 4;
+      this._resultOrListeners = source;
+    },
     then$1$2$onError(f, onError, $R) {
       var currentZone, result, t2,
         t1 = this.$ti;
@@ -9695,14 +10281,6 @@
     then$1$1(f, $R) {
       return this.then$1$2$onError(f, null, $R);
     },
-    _thenAwait$1$2(f, onError, $E) {
-      var result,
-        t1 = this.$ti;
-      t1._bind$1($E)._eval$1("1/(2)")._as(f);
-      result = new A._Future($.Zone__current, $E._eval$1("_Future<0>"));
-      this._addListener$1(new A._FutureListener(result, 3, f, onError, t1._eval$1("@<1>")._bind$1($E)._eval$1("_FutureListener<1,2>")));
-      return result;
-    },
     whenComplete$1(action) {
       var t1, t2, result;
       type$.dynamic_Function._as(action);
@@ -9798,7 +10376,7 @@
       t1._eval$1("1/")._as(value);
       if (t1._eval$1("Future<1>")._is(value))
         if (t1._is(value))
-          A._Future__chainCoreFuture(value, _this);
+          A._Future__chainCoreFutureSync(value, _this);
         else
           _this._chainForeignFuture$1(value);
       else {
@@ -9832,7 +10410,7 @@
         this._chainFuture$1(value);
         return;
       }
-      this._asyncCompleteWithValue$1(t1._precomputed1._as(value));
+      this._asyncCompleteWithValue$1(value);
     },
     _asyncCompleteWithValue$1(value) {
       var _this = this;
@@ -9841,18 +10419,13 @@
       _this._zone.scheduleMicrotask$1(new A._Future__asyncCompleteWithValue_closure(_this, value));
     },
     _chainFuture$1(value) {
-      var _this = this,
-        t1 = _this.$ti;
+      var t1 = this.$ti;
       t1._eval$1("Future<1>")._as(value);
       if (t1._is(value)) {
-        if ((value._async$_state & 16) !== 0) {
-          _this._async$_state ^= 2;
-          _this._zone.scheduleMicrotask$1(new A._Future__chainFuture_closure(_this, value));
-        } else
-          A._Future__chainCoreFuture(value, _this);
+        A._Future__chainCoreFutureAsync(value, this);
         return;
       }
-      _this._chainForeignFuture$1(value);
+      this._chainForeignFuture$1(value);
     },
     _asyncCompleteError$2(error, stackTrace) {
       type$.StackTrace._as(stackTrace);
@@ -9886,13 +10459,13 @@
         t1._completeError$2(error, stackTrace);
       }
     },
-    $signature: 8
+    $signature: 10
   };
   A._Future__chainForeignFuture_closure0.prototype = {
     call$2(error, stackTrace) {
       this.$this._completeError$2(type$.Object._as(error), type$.StackTrace._as(stackTrace));
     },
-    $signature: 37
+    $signature: 26
   };
   A._Future__chainForeignFuture_closure1.prototype = {
     call$0() {
@@ -9900,15 +10473,15 @@
     },
     $signature: 0
   };
-  A._Future__asyncCompleteWithValue_closure.prototype = {
+  A._Future__chainCoreFutureAsync_closure.prototype = {
     call$0() {
-      this.$this._completeWithValue$1(this.value);
+      A._Future__chainCoreFutureSync(this._box_0.source, this.target);
     },
     $signature: 0
   };
-  A._Future__chainFuture_closure.prototype = {
+  A._Future__asyncCompleteWithValue_closure.prototype = {
     call$0() {
-      A._Future__chainCoreFuture(this.value, this.$this);
+      this.$this._completeWithValue$1(this.value);
     },
     $signature: 0
   };
@@ -9944,7 +10517,7 @@
         }
         return;
       }
-      if (type$.Future_dynamic._is(completeResult)) {
+      if (completeResult instanceof A._Future) {
         originalSource = _this._box_1.source;
         t1 = _this._box_0;
         t1.listenerValueOrError = completeResult.then$1$1(new A._Future__propagateToListeners_handleWhenCompleteCallback_closure(originalSource), type$.dynamic);
@@ -9957,7 +10530,7 @@
     call$1(_) {
       return this.originalSource;
     },
-    $signature: 34
+    $signature: 28
   };
   A._Future__propagateToListeners_handleValueCallback.prototype = {
     call$0() {
@@ -10021,7 +10594,7 @@
     call$1(_) {
       return this.streamConsumer.close$0(0);
     },
-    $signature: 32
+    $signature: 29
   };
   A.Stream_length_closure.prototype = {
     call$1(_) {
@@ -10038,7 +10611,6 @@
     },
     $signature: 0
   };
-  A.StreamTransformerBase.prototype = {$isStreamTransformer: 1};
   A._StreamController.prototype = {
     get$_pendingEvents() {
       var t1, _this = this;
@@ -10175,7 +10747,7 @@
         if (result == null)
           try {
             cancelResult = onCancel.call$0();
-            if (type$.Future_void._is(cancelResult))
+            if (cancelResult instanceof A._Future)
               result = cancelResult;
           } catch (exception) {
             e = A.unwrapException(exception);
@@ -10615,7 +11187,6 @@
     },
     $isStreamSubscription: 1
   };
-  A._StreamIterator.prototype = {};
   A._EmptyStream.prototype = {
     listen$4$cancelOnError$onDone$onError(onData, cancelOnError, onDone, onError) {
       var t1 = this.$ti;
@@ -10903,11 +11474,7 @@
   };
   A._rootHandleError_closure.prototype = {
     call$0() {
-      var t1 = this.error,
-        t2 = this.stackTrace;
-      A.checkNotNullable(t1, "error", type$.Object);
-      A.checkNotNullable(t2, "stackTrace", type$.StackTrace);
-      A.Error__throw(t1, t2);
+      A.Error_throwWithStackTrace(this.error, this.stackTrace);
     },
     $signature: 0
   };
@@ -11130,7 +11697,7 @@
           t2._processUncaughtError$3(zone, type$.Object._as(e), t1._as(s));
       }
     },
-    $signature: 31
+    $signature: 34
   };
   A._HashMap.prototype = {
     get$length(_) {
@@ -11325,9 +11892,15 @@
     get$isEmpty(_) {
       return this._collection$_map._collection$_length === 0;
     },
+    get$isNotEmpty(_) {
+      return this._collection$_map._collection$_length !== 0;
+    },
     get$iterator(_) {
       var t1 = this._collection$_map;
       return new A._HashMapKeyIterator(t1, t1._computeKeys$0(), this.$ti._eval$1("_HashMapKeyIterator<1>"));
+    },
+    contains$1(_, element) {
+      return this._collection$_map.containsKey$1(0, element);
     }
   };
   A._HashMapKeyIterator.prototype = {
@@ -11366,6 +11939,12 @@
     get$length(_) {
       return this._collection$_length;
     },
+    get$isEmpty(_) {
+      return this._collection$_length === 0;
+    },
+    get$isNotEmpty(_) {
+      return this._collection$_length !== 0;
+    },
     contains$1(_, object) {
       var nums;
       if ((object & 1073741823) === object) {
@@ -11412,20 +11991,17 @@
       return true;
     },
     remove$1(_, object) {
-      var _this = this;
-      if (typeof object == "string" && object !== "__proto__")
-        return _this._collection$_removeHashTableEntry$2(_this._collection$_strings, object);
-      else if (typeof object == "number" && (object & 1073741823) === object)
-        return _this._collection$_removeHashTableEntry$2(_this._collection$_nums, object);
+      if ((object & 1073741823) === object)
+        return this._collection$_removeHashTableEntry$2(this._collection$_nums, object);
       else
-        return _this._remove$1(0, object);
+        return this._remove$1(0, object);
     },
     _remove$1(_, object) {
       var hash, bucket, index, cell,
         rest = this._collection$_rest;
       if (rest == null)
         return false;
-      hash = J.get$hashCode$(object) & 1073741823;
+      hash = B.JSInt_methods.get$hashCode(object) & 1073741823;
       bucket = rest[hash];
       index = this._findBucketIndex$2(bucket, object);
       if (index < 0)
@@ -11524,34 +12100,73 @@
     },
     $isIterator: 1
   };
-  A.IterableBase.prototype = {};
-  A.ListBase.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
-  A.ListMixin.prototype = {
+  A.ListBase.prototype = {
     get$iterator(receiver) {
-      return new A.ListIterator(receiver, this.get$length(receiver), A.instanceType(receiver)._eval$1("ListIterator<ListMixin.E>"));
+      return new A.ListIterator(receiver, this.get$length(receiver), A.instanceType(receiver)._eval$1("ListIterator<ListBase.E>"));
     },
     elementAt$1(receiver, index) {
       return this.$index(receiver, index);
     },
+    get$isEmpty(receiver) {
+      return this.get$length(receiver) === 0;
+    },
     get$isNotEmpty(receiver) {
-      return this.get$length(receiver) !== 0;
+      return !this.get$isEmpty(receiver);
+    },
+    get$first(receiver) {
+      if (this.get$length(receiver) === 0)
+        throw A.wrapException(A.IterableElementError_noElement());
+      return this.$index(receiver, 0);
     },
     map$1$1(receiver, f, $T) {
       var t1 = A.instanceType(receiver);
-      return new A.MappedListIterable(receiver, t1._bind$1($T)._eval$1("1(ListMixin.E)")._as(f), t1._eval$1("@<ListMixin.E>")._bind$1($T)._eval$1("MappedListIterable<1,2>"));
+      return new A.MappedListIterable(receiver, t1._bind$1($T)._eval$1("1(ListBase.E)")._as(f), t1._eval$1("@<ListBase.E>")._bind$1($T)._eval$1("MappedListIterable<1,2>"));
+    },
+    skip$1(receiver, count) {
+      return A.SubListIterable$(receiver, count, null, A.instanceType(receiver)._eval$1("ListBase.E"));
+    },
+    cast$1$0(receiver, $R) {
+      return new A.CastList(receiver, A.instanceType(receiver)._eval$1("@<ListBase.E>")._bind$1($R)._eval$1("CastList<1,2>"));
     },
     fillRange$3(receiver, start, end, fill) {
       var i;
-      A.instanceType(receiver)._eval$1("ListMixin.E?")._as(fill);
+      A.instanceType(receiver)._eval$1("ListBase.E?")._as(fill);
       A.RangeError_checkValidRange(start, end, this.get$length(receiver));
       for (i = start; i < end; ++i)
         this.$indexSet(receiver, i, fill);
     },
     toString$0(receiver) {
-      return A.IterableBase_iterableToFullString(receiver, "[", "]");
-    }
+      return A.Iterable_iterableToFullString(receiver, "[", "]");
+    },
+    $isEfficientLengthIterable: 1,
+    $isIterable: 1,
+    $isList: 1
   };
-  A.MapBase.prototype = {};
+  A.MapBase.prototype = {
+    forEach$1(receiver, action) {
+      var t2, key, t3,
+        t1 = A.instanceType(receiver);
+      t1._eval$1("~(MapBase.K,MapBase.V)")._as(action);
+      for (t2 = J.get$iterator$ax(this.get$keys(receiver)), t1 = t1._eval$1("MapBase.V"); t2.moveNext$0();) {
+        key = t2.get$current(t2);
+        t3 = this.$index(receiver, key);
+        action.call$2(key, t3 == null ? t1._as(t3) : t3);
+      }
+    },
+    containsKey$1(receiver, key) {
+      return J.contains$1$asx(this.get$keys(receiver), key);
+    },
+    get$length(receiver) {
+      return J.get$length$asx(this.get$keys(receiver));
+    },
+    get$isEmpty(receiver) {
+      return J.get$isEmpty$asx(this.get$keys(receiver));
+    },
+    toString$0(receiver) {
+      return A.MapBase_mapToString(receiver);
+    },
+    $isMap: 1
+  };
   A.MapBase_mapToString_closure.prototype = {
     call$2(k, v) {
       var t2,
@@ -11564,29 +12179,7 @@
       t1._contents = t2 + ": ";
       t1._contents += A.S(v);
     },
-    $signature: 21
-  };
-  A.MapMixin.prototype = {
-    forEach$1(receiver, action) {
-      var t2, key, t3,
-        t1 = A.instanceType(receiver);
-      t1._eval$1("~(MapMixin.K,MapMixin.V)")._as(action);
-      for (t2 = J.get$iterator$ax(this.get$keys(receiver)), t1 = t1._eval$1("MapMixin.V"); t2.moveNext$0();) {
-        key = t2.get$current(t2);
-        t3 = this.$index(receiver, key);
-        action.call$2(key, t3 == null ? t1._as(t3) : t3);
-      }
-    },
-    get$length(receiver) {
-      return J.get$length$asx(this.get$keys(receiver));
-    },
-    get$isEmpty(receiver) {
-      return J.get$isEmpty$asx(this.get$keys(receiver));
-    },
-    toString$0(receiver) {
-      return A.MapBase_mapToString(receiver);
-    },
-    $isMap: 1
+    $signature: 16
   };
   A._UnmodifiableMapMixin.prototype = {
     $indexSet(_, key, value) {
@@ -11604,6 +12197,9 @@
       var t1 = A._instanceType(this);
       J.$indexSet$ax(this._collection$_map, t1._precomputed1._as(key), t1._rest[1]._as(value));
     },
+    containsKey$1(_, key) {
+      return J.containsKey$1$x(this._collection$_map, key);
+    },
     forEach$1(_, action) {
       J.forEach$1$x(this._collection$_map, A._instanceType(this)._eval$1("~(1,2)")._as(action));
     },
@@ -11622,19 +12218,42 @@
     $isMap: 1
   };
   A.UnmodifiableMapView.prototype = {};
-  A.SetMixin.prototype = {
+  A.SetBase.prototype = {
+    get$isEmpty(_) {
+      return this._collection$_length === 0;
+    },
+    get$isNotEmpty(_) {
+      return this._collection$_length !== 0;
+    },
     map$1$1(_, f, $T) {
       var t1 = this.$ti;
       return new A.EfficientLengthMappedIterable(this, t1._bind$1($T)._eval$1("1(2)")._as(f), t1._eval$1("@<1>")._bind$1($T)._eval$1("EfficientLengthMappedIterable<1,2>"));
     },
     toString$0(_) {
-      return A.IterableBase_iterableToFullString(this, "{", "}");
-    }
+      return A.Iterable_iterableToFullString(this, "{", "}");
+    },
+    skip$1(_, n) {
+      return A.SkipIterable_SkipIterable(this, n, this.$ti._precomputed1);
+    },
+    elementAt$1(_, index) {
+      var iterator, skipCount, t1, _this = this;
+      A.RangeError_checkNotNegative(index, "index");
+      iterator = A._LinkedHashSetIterator$(_this, _this._collection$_modifications, _this.$ti._precomputed1);
+      for (skipCount = index; iterator.moveNext$0();) {
+        if (skipCount === 0) {
+          t1 = iterator._collection$_current;
+          return t1 == null ? iterator.$ti._precomputed1._as(t1) : t1;
+        }
+        --skipCount;
+      }
+      throw A.wrapException(A.IndexError$withLength(index, index - skipCount, _this, "index"));
+    },
+    $isEfficientLengthIterable: 1,
+    $isIterable: 1,
+    $isSet: 1
   };
-  A._SetBase.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isSet: 1};
-  A._ListBase_Object_ListMixin.prototype = {};
+  A._SetBase.prototype = {};
   A._UnmodifiableMapView_MapView__UnmodifiableMapMixin.prototype = {};
-  A.__SetBase_Object_SetMixin.prototype = {};
   A._JsonMap.prototype = {
     $index(_, key) {
       var result,
@@ -11756,6 +12375,9 @@
         t1 = new J.ArrayIterator(t1, t1.length, A._arrayInstanceType(t1)._eval$1("ArrayIterator<1>"));
       }
       return t1;
+    },
+    contains$1(_, key) {
+      return this._convert$_parent.containsKey$1(0, key);
     }
   };
   A.Utf8Decoder__decoder_closure.prototype = {
@@ -11768,7 +12390,7 @@
       }
       return null;
     },
-    $signature: 19
+    $signature: 4
   };
   A.Utf8Decoder__decoderNonfatal_closure.prototype = {
     call$0() {
@@ -11780,7 +12402,7 @@
       }
       return null;
     },
-    $signature: 19
+    $signature: 4
   };
   A.AsciiCodec.prototype = {
     encode$1(source) {
@@ -11789,12 +12411,15 @@
   };
   A._UnicodeSubsetEncoder.prototype = {
     convert$1(string) {
-      var $length, result, t1, i, codeUnit;
+      var stringLength, $length, result, t1, i, codeUnit;
       A._asString(string);
-      $length = A.RangeError_checkValidRange(0, null, string.length) - 0;
+      stringLength = string.length;
+      $length = A.RangeError_checkValidRange(0, null, stringLength) - 0;
       result = new Uint8Array($length);
       for (t1 = ~this._subsetMask, i = 0; i < $length; ++i) {
-        codeUnit = B.JSString_methods._codeUnitAt$1(string, i);
+        if (!(i < stringLength))
+          return A.ioore(string, i);
+        codeUnit = string.charCodeAt(i);
         if ((codeUnit & t1) !== 0)
           throw A.wrapException(A.ArgumentError$value(string, "string", "Contains invalid characters."));
         if (!(i < $length))
@@ -11807,18 +12432,27 @@
   A.AsciiEncoder.prototype = {};
   A.Base64Codec.prototype = {
     normalize$3(_, source, start, end) {
-      var inverseAlphabet, t1, i, sliceStart, buffer, firstPadding, firstPaddingSourceIndex, paddingCount, i0, char, i1, digit1, digit2, char0, value, t2, t3, endLength, $length,
-        _s31_ = "Invalid base64 encoding length ";
-      end = A.RangeError_checkValidRange(start, end, source.length);
+      var inverseAlphabet, t2, i, sliceStart, buffer, firstPadding, firstPaddingSourceIndex, paddingCount, i0, char, i1, digit1, t3, digit2, char0, value, endLength, $length,
+        _s64_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
+        _s31_ = "Invalid base64 encoding length ",
+        t1 = source.length;
+      end = A.RangeError_checkValidRange(start, end, t1);
       inverseAlphabet = $.$get$_Base64Decoder__inverseAlphabet();
-      for (t1 = inverseAlphabet.length, i = start, sliceStart = i, buffer = null, firstPadding = -1, firstPaddingSourceIndex = -1, paddingCount = 0; i < end; i = i0) {
+      for (t2 = inverseAlphabet.length, i = start, sliceStart = i, buffer = null, firstPadding = -1, firstPaddingSourceIndex = -1, paddingCount = 0; i < end; i = i0) {
         i0 = i + 1;
-        char = B.JSString_methods._codeUnitAt$1(source, i);
+        if (!(i < t1))
+          return A.ioore(source, i);
+        char = source.charCodeAt(i);
         if (char === 37) {
           i1 = i0 + 2;
           if (i1 <= end) {
-            digit1 = A.hexDigitValue(B.JSString_methods._codeUnitAt$1(source, i0));
-            digit2 = A.hexDigitValue(B.JSString_methods._codeUnitAt$1(source, i0 + 1));
+            if (!(i0 < t1))
+              return A.ioore(source, i0);
+            digit1 = A.hexDigitValue(source.charCodeAt(i0));
+            t3 = i0 + 1;
+            if (!(t3 < t1))
+              return A.ioore(source, t3);
+            digit2 = A.hexDigitValue(source.charCodeAt(t3));
             char0 = digit1 * 16 + digit2 - (digit2 & 256);
             if (char0 === 37)
               char0 = -1;
@@ -11828,21 +12462,23 @@
         } else
           char0 = char;
         if (0 <= char0 && char0 <= 127) {
-          if (!(char0 >= 0 && char0 < t1))
+          if (!(char0 >= 0 && char0 < t2))
             return A.ioore(inverseAlphabet, char0);
           value = inverseAlphabet[char0];
           if (value >= 0) {
-            char0 = B.JSString_methods.codeUnitAt$1("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", value);
+            if (!(value < 64))
+              return A.ioore(_s64_, value);
+            char0 = _s64_.charCodeAt(value);
             if (char0 === char)
               continue;
             char = char0;
           } else {
             if (value === -1) {
               if (firstPadding < 0) {
-                t2 = buffer == null ? null : buffer._contents.length;
-                if (t2 == null)
-                  t2 = 0;
-                firstPadding = t2 + (i - sliceStart);
+                t3 = buffer == null ? null : buffer._contents.length;
+                if (t3 == null)
+                  t3 = 0;
+                firstPadding = t3 + (i - sliceStart);
                 firstPaddingSourceIndex = i;
               }
               ++paddingCount;
@@ -11854,11 +12490,11 @@
           if (value !== -2) {
             if (buffer == null) {
               buffer = new A.StringBuffer("");
-              t2 = buffer;
+              t3 = buffer;
             } else
-              t2 = buffer;
-            t3 = t2._contents += B.JSString_methods.substring$2(source, sliceStart, i);
-            t2._contents = t3 + A.Primitives_stringFromCharCode(char);
+              t3 = buffer;
+            t3._contents += B.JSString_methods.substring$2(source, sliceStart, i);
+            t3._contents += A.Primitives_stringFromCharCode(char);
             sliceStart = i0;
             continue;
           }
@@ -11899,7 +12535,7 @@
   A.Base64Encoder.prototype = {};
   A.Codec.prototype = {};
   A._FusedCodec.prototype = {};
-  A.Converter.prototype = {};
+  A.Converter.prototype = {$isStreamTransformer: 1};
   A.Encoding.prototype = {};
   A.JsonUnsupportedObjectError.prototype = {
     toString$0(_) {
@@ -11914,15 +12550,11 @@
   };
   A.JsonCodec.prototype = {
     decode$2$reviver(_, source, reviver) {
-      var t1;
-      type$.nullable_nullable_Object_Function_2_nullable_Object_and_nullable_Object._as(reviver);
-      t1 = A._parseJson(source, this.get$decoder()._reviver);
+      var t1 = A._parseJson(source, this.get$decoder()._reviver);
       return t1;
     },
     encode$2$toEncodable(value, toEncodable) {
-      var t1;
-      type$.nullable_nullable_Object_Function_dynamic._as(toEncodable);
-      t1 = A._JsonStringStringifier_stringify(value, this.get$encoder()._toEncodable, null);
+      var t1 = A._JsonStringStringifier_stringify(value, this.get$encoder()._toEncodable, null);
       return t1;
     },
     get$encoder() {
@@ -11939,19 +12571,19 @@
       var offset, i, charCode, t1, t2, _this = this,
         $length = s.length;
       for (offset = 0, i = 0; i < $length; ++i) {
-        charCode = B.JSString_methods._codeUnitAt$1(s, i);
+        charCode = s.charCodeAt(i);
         if (charCode > 92) {
           if (charCode >= 55296) {
             t1 = charCode & 64512;
             if (t1 === 55296) {
               t2 = i + 1;
-              t2 = !(t2 < $length && (B.JSString_methods._codeUnitAt$1(s, t2) & 64512) === 56320);
+              t2 = !(t2 < $length && (s.charCodeAt(t2) & 64512) === 56320);
             } else
               t2 = false;
             if (!t2)
               if (t1 === 56320) {
                 t1 = i - 1;
-                t1 = !(t1 >= 0 && (B.JSString_methods.codeUnitAt$1(s, t1) & 64512) === 55296);
+                t1 = !(t1 >= 0 && (s.charCodeAt(t1) & 64512) === 55296);
               } else
                 t1 = false;
             else
@@ -12138,7 +12770,7 @@
       B.JSArray_methods.$indexSet(t1, t2.i++, key);
       B.JSArray_methods.$indexSet(t1, t2.i++, value);
     },
-    $signature: 21
+    $signature: 16
   };
   A._JsonStringStringifier.prototype = {
     get$_partialResult() {
@@ -12158,23 +12790,22 @@
       this._sink.writeCharCode$1(charCode);
     }
   };
-  A.Utf8Codec.prototype = {
-    get$encoder() {
-      return B.C_Utf8Encoder;
-    }
-  };
+  A.Utf8Codec.prototype = {};
   A.Utf8Encoder.prototype = {
     convert$1(string) {
-      var end, $length, t1, encoder;
+      var stringLength, end, $length, t1, encoder, t2;
       A._asString(string);
-      end = A.RangeError_checkValidRange(0, null, string.length);
+      stringLength = string.length;
+      end = A.RangeError_checkValidRange(0, null, stringLength);
       $length = end - 0;
       if ($length === 0)
         return new Uint8Array(0);
       t1 = new Uint8Array($length * 3);
       encoder = new A._Utf8Encoder(t1);
       if (encoder._fillBuffer$3(string, 0, end) !== end) {
-        B.JSString_methods.codeUnitAt$1(string, end - 1);
+        t2 = end - 1;
+        if (!(t2 >= 0 && t2 < stringLength))
+          return A.ioore(string, t2);
         encoder._writeReplacementCharacter$0();
       }
       return B.NativeUint8List_methods.sublist$2(t1, 0, encoder._bufferIndex);
@@ -12229,56 +12860,67 @@
       }
     },
     _fillBuffer$3(str, start, end) {
-      var t1, t2, stringIndex, codeUnit, t3, stringIndex0, t4, _this = this;
-      if (start !== end && (B.JSString_methods.codeUnitAt$1(str, end - 1) & 64512) === 55296)
+      var t1, t2, t3, stringIndex, codeUnit, t4, t5, _this = this;
+      if (start !== end) {
+        t1 = end - 1;
+        if (!(t1 >= 0 && t1 < str.length))
+          return A.ioore(str, t1);
+        t1 = (str.charCodeAt(t1) & 64512) === 55296;
+      } else
+        t1 = false;
+      if (t1)
         --end;
-      for (t1 = _this._buffer, t2 = t1.length, stringIndex = start; stringIndex < end; ++stringIndex) {
-        codeUnit = B.JSString_methods._codeUnitAt$1(str, stringIndex);
+      for (t1 = _this._buffer, t2 = t1.length, t3 = str.length, stringIndex = start; stringIndex < end; ++stringIndex) {
+        if (!(stringIndex < t3))
+          return A.ioore(str, stringIndex);
+        codeUnit = str.charCodeAt(stringIndex);
         if (codeUnit <= 127) {
-          t3 = _this._bufferIndex;
-          if (t3 >= t2)
+          t4 = _this._bufferIndex;
+          if (t4 >= t2)
             break;
-          _this._bufferIndex = t3 + 1;
-          t1[t3] = codeUnit;
+          _this._bufferIndex = t4 + 1;
+          t1[t4] = codeUnit;
         } else {
-          t3 = codeUnit & 64512;
-          if (t3 === 55296) {
+          t4 = codeUnit & 64512;
+          if (t4 === 55296) {
             if (_this._bufferIndex + 4 > t2)
               break;
-            stringIndex0 = stringIndex + 1;
-            if (_this._writeSurrogate$2(codeUnit, B.JSString_methods._codeUnitAt$1(str, stringIndex0)))
-              stringIndex = stringIndex0;
-          } else if (t3 === 56320) {
+            t4 = stringIndex + 1;
+            if (!(t4 < t3))
+              return A.ioore(str, t4);
+            if (_this._writeSurrogate$2(codeUnit, str.charCodeAt(t4)))
+              stringIndex = t4;
+          } else if (t4 === 56320) {
             if (_this._bufferIndex + 3 > t2)
               break;
             _this._writeReplacementCharacter$0();
           } else if (codeUnit <= 2047) {
-            t3 = _this._bufferIndex;
-            t4 = t3 + 1;
-            if (t4 >= t2)
+            t4 = _this._bufferIndex;
+            t5 = t4 + 1;
+            if (t5 >= t2)
               break;
-            _this._bufferIndex = t4;
-            if (!(t3 < t2))
-              return A.ioore(t1, t3);
-            t1[t3] = codeUnit >>> 6 | 192;
-            _this._bufferIndex = t4 + 1;
-            t1[t4] = codeUnit & 63 | 128;
-          } else {
-            t3 = _this._bufferIndex;
-            if (t3 + 2 >= t2)
-              break;
-            t4 = _this._bufferIndex = t3 + 1;
-            if (!(t3 < t2))
-              return A.ioore(t1, t3);
-            t1[t3] = codeUnit >>> 12 | 224;
-            t3 = _this._bufferIndex = t4 + 1;
+            _this._bufferIndex = t5;
             if (!(t4 < t2))
               return A.ioore(t1, t4);
-            t1[t4] = codeUnit >>> 6 & 63 | 128;
-            _this._bufferIndex = t3 + 1;
-            if (!(t3 < t2))
-              return A.ioore(t1, t3);
-            t1[t3] = codeUnit & 63 | 128;
+            t1[t4] = codeUnit >>> 6 | 192;
+            _this._bufferIndex = t5 + 1;
+            t1[t5] = codeUnit & 63 | 128;
+          } else {
+            t4 = _this._bufferIndex;
+            if (t4 + 2 >= t2)
+              break;
+            t5 = _this._bufferIndex = t4 + 1;
+            if (!(t4 < t2))
+              return A.ioore(t1, t4);
+            t1[t4] = codeUnit >>> 12 | 224;
+            t4 = _this._bufferIndex = t5 + 1;
+            if (!(t5 < t2))
+              return A.ioore(t1, t5);
+            t1[t5] = codeUnit >>> 6 & 63 | 128;
+            _this._bufferIndex = t4 + 1;
+            if (!(t4 < t2))
+              return A.ioore(t1, t4);
+            t1[t4] = codeUnit & 63 | 128;
           }
         }
       }
@@ -12333,7 +12975,10 @@
       return _this.decodeGeneral$4(bytes, start, end, single);
     },
     decodeGeneral$4(bytes, start, end, single) {
-      var byte, t2, type, t3, i0, markEnd, i1, m, _this = this, _65533 = 65533,
+      var byte, t2, type, t3, i0, markEnd, i1, m, _this = this,
+        _s256_ = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFFFFFFFFFFFFFFGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHJEEBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBKCCCCCCCCCCCCDCLONNNMEEEEEEEEEEE",
+        _s144_ = " \x000:XECCCCCN:lDb \x000:XECCCCCNvlDb \x000:XECCCCCN:lDb AAAAA\x00\x00\x00\x00\x00AAAAA00000AAAAA:::::AAAAAGG000AAAAA00KKKAAAAAG::::AAAAA:IIIIAAAAA000\x800AAAAA\x00\x00\x00\x00 AAAAA",
+        _65533 = 65533,
         state = _this._state,
         char = _this._charOrIndex,
         buffer = new A.StringBuffer(""),
@@ -12345,9 +12990,14 @@
       $label0$0:
         for (t2 = _this.allowMalformed; true;) {
           for (; true; i = i0) {
-            type = B.JSString_methods._codeUnitAt$1("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFFFFFFFFFFFFFFFGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHIHHHJEEBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBKCCCCCCCCCCCCDCLONNNMEEEEEEEEEEE", byte) & 31;
+            if (!(byte >= 0 && byte < 256))
+              return A.ioore(_s256_, byte);
+            type = _s256_.charCodeAt(byte) & 31;
             char = state <= 32 ? byte & 61694 >>> type : (byte & 63 | char << 6) >>> 0;
-            state = B.JSString_methods._codeUnitAt$1(" \x000:XECCCCCN:lDb \x000:XECCCCCNvlDb \x000:XECCCCCN:lDb AAAAA\x00\x00\x00\x00\x00AAAAA00000AAAAA:::::AAAAAGG000AAAAA00KKKAAAAAG::::AAAAA:IIIIAAAAA000\x800AAAAA\x00\x00\x00\x00 AAAAA", state + type);
+            t3 = state + type;
+            if (!(t3 >= 0 && t3 < 144))
+              return A.ioore(_s144_, t3);
+            state = _s144_.charCodeAt(t3);
             if (state === 0) {
               buffer._contents += A.Primitives_stringFromCharCode(char);
               if (i === end)
@@ -12445,16 +13095,16 @@
       t1._contents += A.Error_safeToString(value);
       t2.comma = ", ";
     },
-    $signature: 29
+    $signature: 39
   };
   A.DateTime.prototype = {
     $eq(_, other) {
       if (other == null)
         return false;
-      return other instanceof A.DateTime && this._value === other._value && true;
+      return other instanceof A.DateTime && this._core$_value === other._core$_value && true;
     },
     get$hashCode(_) {
-      var t1 = this._value;
+      var t1 = this._core$_value;
       return (t1 ^ B.JSInt_methods._shrOtherPositive$1(t1, 30)) & 1073741823;
     },
     toString$0(_) {
@@ -12488,7 +13138,7 @@
       minutesPadding = minutes < 10 ? "0" : "";
       seconds = B.JSInt_methods._tdivFast$1(microseconds, 1000000);
       secondsPadding = seconds < 10 ? "0" : "";
-      return "" + Math.abs(hours) + ":" + minutesPadding + minutes + ":" + secondsPadding + seconds + "." + B.JSString_methods.padLeft$2(B.JSInt_methods.toString$0(microseconds % 1000000), 6, "0");
+      return "" + hours + ":" + minutesPadding + minutes + ":" + secondsPadding + seconds + "." + B.JSString_methods.padLeft$2(B.JSInt_methods.toString$0(microseconds % 1000000), 6, "0");
     }
   };
   A.Error.prototype = {
@@ -12505,11 +13155,6 @@
     }
   };
   A.TypeError.prototype = {};
-  A.NullThrownError.prototype = {
-    toString$0(_) {
-      return "Throw of null.";
-    }
-  };
   A.ArgumentError.prototype = {
     get$_errorName() {
       return "Invalid argument" + (!this._hasValue ? "(s)" : "");
@@ -12526,10 +13171,16 @@
         prefix = _this.get$_errorName() + nameString + messageString;
       if (!_this._hasValue)
         return prefix;
-      return prefix + _this.get$_errorExplanation() + ": " + A.Error_safeToString(_this.invalidValue);
+      return prefix + _this.get$_errorExplanation() + ": " + A.Error_safeToString(_this.get$invalidValue());
+    },
+    get$invalidValue() {
+      return this.invalidValue;
     }
   };
   A.RangeError.prototype = {
+    get$invalidValue() {
+      return A._asNumQ(this.invalidValue);
+    },
     get$_errorName() {
       return "RangeError";
     },
@@ -12549,6 +13200,9 @@
     }
   };
   A.IndexError.prototype = {
+    get$invalidValue() {
+      return A._asInt(this.invalidValue);
+    },
     get$_errorName() {
       return "RangeError";
     },
@@ -12623,11 +13277,6 @@
     },
     $isError: 1
   };
-  A.CyclicInitializationError.prototype = {
-    toString$0(_) {
-      return "Reading static variable '" + this.variableName + "' during its initialization";
-    }
-  };
   A._Exception.prototype = {
     toString$0(_) {
       return "Exception: " + this.message;
@@ -12636,7 +13285,7 @@
   };
   A.FormatException.prototype = {
     toString$0(_) {
-      var t1, lineNum, lineStart, previousCharWasCR, i, char, lineEnd, end, start, prefix, postfix,
+      var t1, lineEnd, lineNum, lineStart, previousCharWasCR, i, char, end, start, prefix, postfix,
         message = this.message,
         report = "" !== message ? "FormatException: " + message : "FormatException",
         offset = this.offset,
@@ -12653,8 +13302,10 @@
             source = B.JSString_methods.substring$2(source, 0, 75) + "...";
           return report + "\n" + source;
         }
-        for (lineNum = 1, lineStart = 0, previousCharWasCR = false, i = 0; i < offset; ++i) {
-          char = B.JSString_methods._codeUnitAt$1(source, i);
+        for (lineEnd = source.length, lineNum = 1, lineStart = 0, previousCharWasCR = false, i = 0; i < offset; ++i) {
+          if (!(i < lineEnd))
+            return A.ioore(source, i);
+          char = source.charCodeAt(i);
           if (char === 10) {
             if (lineStart !== i || !previousCharWasCR)
               ++lineNum;
@@ -12667,9 +13318,10 @@
           }
         }
         report = lineNum > 1 ? report + (" (at line " + lineNum + ", character " + (offset - lineStart + 1) + ")\n") : report + (" (at character " + (offset + 1) + ")\n");
-        lineEnd = source.length;
         for (i = offset; i < lineEnd; ++i) {
-          char = B.JSString_methods.codeUnitAt$1(source, i);
+          if (!(i >= 0))
+            return A.ioore(source, i);
+          char = source.charCodeAt(i);
           if (char === 10 || char === 13) {
             lineEnd = i;
             break;
@@ -12706,10 +13358,19 @@
     $isException: 1
   };
   A.Iterable.prototype = {
+    cast$1$0(_, $R) {
+      return A.CastIterable_CastIterable(this, A._instanceType(this)._eval$1("Iterable.E"), $R);
+    },
     map$1$1(_, toElement, $T) {
       var t1 = A._instanceType(this);
       return A.MappedIterable_MappedIterable(this, t1._bind$1($T)._eval$1("1(Iterable.E)")._as(toElement), t1._eval$1("Iterable.E"), $T);
     },
+    toList$1$growable(_, growable) {
+      return A.List_List$of(this, growable, A._instanceType(this)._eval$1("Iterable.E"));
+    },
+    toList$0($receiver) {
+      return this.toList$1$growable($receiver, true);
+    },
     get$length(_) {
       var count,
         it = this.get$iterator(this);
@@ -12720,6 +13381,12 @@
     get$isEmpty(_) {
       return !this.get$iterator(this).moveNext$0();
     },
+    get$isNotEmpty(_) {
+      return !this.get$isEmpty(this);
+    },
+    skip$1(_, count) {
+      return A.SkipIterable_SkipIterable(this, count, A._instanceType(this)._eval$1("Iterable.E"));
+    },
     skipWhile$1(_, test) {
       var t1 = A._instanceType(this);
       return new A.SkipWhileIterable(this, t1._eval$1("bool(Iterable.E)")._as(test), t1._eval$1("SkipWhileIterable<Iterable.E>"));
@@ -12741,21 +13408,20 @@
       return result;
     },
     elementAt$1(_, index) {
-      var t1, elementIndex, element;
+      var iterator, skipCount;
       A.RangeError_checkNotNegative(index, "index");
-      for (t1 = this.get$iterator(this), elementIndex = 0; t1.moveNext$0();) {
-        element = t1.get$current(t1);
-        if (index === elementIndex)
-          return element;
-        ++elementIndex;
+      iterator = this.get$iterator(this);
+      for (skipCount = index; iterator.moveNext$0();) {
+        if (skipCount === 0)
+          return iterator.get$current(iterator);
+        --skipCount;
       }
-      throw A.wrapException(A.IndexError$(index, this, "index", null, elementIndex));
+      throw A.wrapException(A.IndexError$withLength(index, index - skipCount, this, "index"));
     },
     toString$0(_) {
-      return A.IterableBase_iterableToShortString(this, "(", ")");
+      return A.Iterable_iterableToShortString(this, "(", ")");
     }
   };
-  A.Iterator.prototype = {};
   A.Null.prototype = {
     get$hashCode(_) {
       return A.Object.prototype.get$hashCode.call(this, this);
@@ -12775,8 +13441,10 @@
       return "Instance of '" + A.Primitives_objectTypeName(this) + "'";
     },
     noSuchMethod$1(_, invocation) {
-      type$.Invocation._as(invocation);
-      throw A.wrapException(A.NoSuchMethodError$(this, invocation.get$memberName(), invocation.get$positionalArguments(), invocation.get$namedArguments()));
+      throw A.wrapException(A.NoSuchMethodError_NoSuchMethodError$withInvocation(this, type$.Invocation._as(invocation)));
+    },
+    get$runtimeType(_) {
+      return A.getRuntimeTypeOfDartObject(this);
     },
     toString() {
       return this.toString$0(this);
@@ -12821,7 +13489,7 @@
       }
       return map;
     },
-    $signature: 27
+    $signature: 40
   };
   A.Uri__parseIPv4Address_error.prototype = {
     call$2(msg, position) {
@@ -12833,7 +13501,7 @@
     call$2(msg, position) {
       throw A.wrapException(A.FormatException$("Illegal IPv6 address, " + msg, this.host, position));
     },
-    $signature: 25
+    $signature: 45
   };
   A.Uri_parseIPv6Address_parseHex.prototype = {
     call$2(start, end) {
@@ -12845,7 +13513,7 @@
         this.error.call$2("each part must be in the range of `0x0..0xFFFF`", start);
       return value;
     },
-    $signature: 26
+    $signature: 60
   };
   A._Uri.prototype = {
     get$_text() {
@@ -12881,11 +13549,18 @@
       return value;
     },
     get$pathSegments() {
-      var pathToSplit, result, _this = this,
+      var pathToSplit, t1, result, _this = this,
         value = _this.___Uri_pathSegments_FI;
       if (value === $) {
         pathToSplit = _this.path;
-        if (pathToSplit.length !== 0 && B.JSString_methods._codeUnitAt$1(pathToSplit, 0) === 47)
+        t1 = pathToSplit.length;
+        if (t1 !== 0) {
+          if (0 >= t1)
+            return A.ioore(pathToSplit, 0);
+          t1 = pathToSplit.charCodeAt(0) === 47;
+        } else
+          t1 = false;
+        if (t1)
           pathToSplit = B.JSString_methods.substring$1(pathToSplit, 1);
         result = pathToSplit.length === 0 ? B.List_empty : A.List_List$unmodifiable(new A.MappedListIterable(A._setArrayType(pathToSplit.split("/"), type$.JSArray_String), type$.dynamic_Function_String._as(A.core_Uri_decodeComponent$closure()), type$.MappedListIterable_String_dynamic), type$.String);
         _this.___Uri_pathSegments_FI !== $ && A.throwLateFieldADI("pathSegments");
@@ -12947,12 +13622,13 @@
       return A._caseInsensitiveCompareStart(scheme, thisScheme, 0) >= 0;
     },
     _mergePaths$2(base, reference) {
-      var backCount, refStart, baseEnd, newEnd, delta, t1;
+      var backCount, refStart, baseEnd, t1, newEnd, delta, t2, t3;
       for (backCount = 0, refStart = 0; B.JSString_methods.startsWith$2(reference, "../", refStart);) {
         refStart += 3;
         ++backCount;
       }
       baseEnd = B.JSString_methods.lastIndexOf$1(base, "/");
+      t1 = base.length;
       while (true) {
         if (!(baseEnd > 0 && backCount > 0))
           break;
@@ -12960,15 +13636,24 @@
         if (newEnd < 0)
           break;
         delta = baseEnd - newEnd;
-        t1 = delta !== 2;
-        if (!t1 || delta === 3)
-          if (B.JSString_methods.codeUnitAt$1(base, newEnd + 1) === 46)
-            t1 = !t1 || B.JSString_methods.codeUnitAt$1(base, newEnd + 2) === 46;
+        t2 = delta !== 2;
+        if (!t2 || delta === 3) {
+          t3 = newEnd + 1;
+          if (!(t3 < t1))
+            return A.ioore(base, t3);
+          if (base.charCodeAt(t3) === 46)
+            if (t2) {
+              t2 = newEnd + 2;
+              if (!(t2 < t1))
+                return A.ioore(base, t2);
+              t2 = base.charCodeAt(t2) === 46;
+            } else
+              t2 = true;
           else
-            t1 = false;
-        else
-          t1 = false;
-        if (t1)
+            t2 = false;
+        } else
+          t2 = false;
+        if (t2)
           break;
         --backCount;
         baseEnd = newEnd;
@@ -13061,7 +13746,7 @@
       if ((t1 == null ? "" : t1) !== "")
         throw A.wrapException(A.UnsupportedError$(string$.Cannotff));
       t1 = $.$get$_Uri__isWindowsCached();
-      if (A.boolConversionCheck(t1))
+      if (t1)
         t1 = A._Uri__toWindowsFilePath(_this);
       else {
         if (_this._host != null && _this.get$host(_this) !== "")
@@ -13139,9 +13824,9 @@
   };
   A._Uri__makePath_closure.prototype = {
     call$1(s) {
-      return A._Uri__uriEncode(B.List_qg40, A._asString(s), B.C_Utf8Codec, false);
+      return A._Uri__uriEncode(B.List_XRg0, A._asString(s), B.C_Utf8Codec, false);
     },
-    $signature: 23
+    $signature: 17
   };
   A.UriData.prototype = {
     get$uri() {
@@ -13156,11 +13841,11 @@
         queryIndex = B.JSString_methods.indexOf$2(t2, "?", t1);
         end = t2.length;
         if (queryIndex >= 0) {
-          query = A._Uri__normalizeOrSubstring(t2, queryIndex + 1, end, B.List_CVk, false);
+          query = A._Uri__normalizeOrSubstring(t2, queryIndex + 1, end, B.List_oFp, false, false);
           end = queryIndex;
         } else
           query = _null;
-        t1 = _this._uriCache = new A._DataUri("data", "", _null, _null, A._Uri__normalizeOrSubstring(t2, t1, end, B.List_qg4, false), query, _null);
+        t1 = _this._uriCache = new A._DataUri("data", "", _null, _null, A._Uri__normalizeOrSubstring(t2, t1, end, B.List_XRg, false, false), query, _null);
       }
       return t1;
     },
@@ -13182,31 +13867,38 @@
       B.NativeUint8List_methods.fillRange$3(t1, 0, 96, defaultTransition);
       return t1;
     },
-    $signature: 28
+    $signature: 25
   };
   A._createTables_setChars.prototype = {
     call$3(target, chars, transition) {
       var t1, i, t2;
       for (t1 = chars.length, i = 0; i < t1; ++i) {
-        t2 = B.JSString_methods._codeUnitAt$1(chars, i) ^ 96;
+        t2 = chars.charCodeAt(i) ^ 96;
         if (!(t2 < 96))
           return A.ioore(target, t2);
         target[t2] = transition;
       }
     },
-    $signature: 22
+    $signature: 18
   };
   A._createTables_setRange.prototype = {
     call$3(target, range, transition) {
-      var i, n, t1;
-      for (i = B.JSString_methods._codeUnitAt$1(range, 0), n = B.JSString_methods._codeUnitAt$1(range, 1); i <= n; ++i) {
+      var i, n,
+        t1 = range.length;
+      if (0 >= t1)
+        return A.ioore(range, 0);
+      i = range.charCodeAt(0);
+      if (1 >= t1)
+        return A.ioore(range, 1);
+      n = range.charCodeAt(1);
+      for (; i <= n; ++i) {
         t1 = (i ^ 96) >>> 0;
         if (!(t1 < 96))
           return A.ioore(target, t1);
         target[t1] = transition;
       }
     },
-    $signature: 22
+    $signature: 18
   };
   A._SimpleUri.prototype = {
     get$hasAuthority() {
@@ -13278,7 +13970,7 @@
       return t1 < t2.length ? B.JSString_methods.substring$1(t2, t1 + 1) : "";
     },
     get$pathSegments() {
-      var parts, i,
+      var parts, t2, i,
         start = this._pathStart,
         end = this._queryStart,
         t1 = this._uri;
@@ -13287,11 +13979,14 @@
       if (start === end)
         return B.List_empty;
       parts = A._setArrayType([], type$.JSArray_String);
-      for (i = start; i < end; ++i)
-        if (B.JSString_methods.codeUnitAt$1(t1, i) === 47) {
+      for (t2 = t1.length, i = start; i < end; ++i) {
+        if (!(i >= 0 && i < t2))
+          return A.ioore(t1, i);
+        if (t1.charCodeAt(i) === 47) {
           B.JSArray_methods.add$1(parts, B.JSString_methods.substring$2(t1, start, i));
           start = i + 1;
         }
+      }
       B.JSArray_methods.add$1(parts, B.JSString_methods.substring$2(t1, start, end));
       return A.List_List$unmodifiable(parts, type$.String);
     },
@@ -13391,9 +14086,11 @@
         ++backCount;
         refStart = refStart0;
       }
-      for (insert = ""; baseEnd > baseStart0;) {
+      for (t3 = baseUri.length, insert = ""; baseEnd > baseStart0;) {
         --baseEnd;
-        if (B.JSString_methods.codeUnitAt$1(baseUri, baseEnd) === 47) {
+        if (!(baseEnd >= 0 && baseEnd < t3))
+          return A.ioore(baseUri, baseEnd);
+        if (baseUri.charCodeAt(baseEnd) === 47) {
           if (backCount === 0) {
             insert = "/";
             break;
@@ -13427,7 +14124,7 @@
         throw A.wrapException(A.UnsupportedError$(string$.Cannotff));
       }
       t3 = $.$get$_Uri__isWindowsCached();
-      if (A.boolConversionCheck(t3))
+      if (t3)
         t1 = A._Uri__toWindowsFilePath(_this);
       else {
         if (_this._hostStart < _this._portStart)
@@ -13474,12 +14171,16 @@
   };
   A.AnchorElement.prototype = {
     toString$0(receiver) {
-      return String(receiver);
+      var t1 = String(receiver);
+      t1.toString;
+      return t1;
     }
   };
   A.AreaElement.prototype = {
     toString$0(receiver) {
-      return String(receiver);
+      var t1 = String(receiver);
+      t1.toString;
+      return t1;
     }
   };
   A.Blob.prototype = {};
@@ -13496,7 +14197,9 @@
   A.CssRule.prototype = {$isCssRule: 1};
   A.CssStyleDeclaration.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     }
   };
   A.CssStyleDeclarationBase.prototype = {};
@@ -13517,26 +14220,37 @@
       return receiver.length;
     },
     $index(receiver, index) {
-      return receiver[A._asInt(index)];
+      var t1 = receiver[A._asInt(index)];
+      t1.toString;
+      return t1;
     }
   };
   A.DomException.prototype = {
     toString$0(receiver) {
-      return String(receiver);
+      var t1 = String(receiver);
+      t1.toString;
+      return t1;
     }
   };
   A.DomRectList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.Rectangle_num._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -13612,16 +14326,23 @@
   };
   A.DomStringList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       A._asString(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -13637,28 +14358,39 @@
   };
   A.DomTokenList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     }
   };
   A.Element.prototype = {
     toString$0(receiver) {
-      return receiver.localName;
+      var t1 = receiver.localName;
+      t1.toString;
+      return t1;
     }
   };
   A.EventTarget.prototype = {};
   A.File.prototype = {$isFile: 1};
   A.FileList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.File._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -13685,21 +14417,30 @@
   A.Gamepad.prototype = {$isGamepad: 1};
   A.History.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     }
   };
   A.HtmlCollection.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.Node._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -13715,7 +14456,9 @@
   };
   A.Location.prototype = {
     toString$0(receiver) {
-      return String(receiver);
+      var t1 = String(receiver);
+      t1.toString;
+      return t1;
     }
   };
   A.MediaList.prototype = {
@@ -13724,18 +14467,25 @@
     }
   };
   A.MidiInputMap.prototype = {
+    containsKey$1(receiver, key) {
+      return A.convertNativeToDart_Dictionary(receiver.get(key)) != null;
+    },
     $index(receiver, key) {
       return A.convertNativeToDart_Dictionary(receiver.get(A._asString(key)));
     },
     forEach$1(receiver, f) {
-      var entries, entry;
+      var entries, entry, t1;
       type$.void_Function_String_dynamic._as(f);
       entries = receiver.entries();
       for (; true;) {
         entry = entries.next();
-        if (entry.done)
+        t1 = entry.done;
+        t1.toString;
+        if (t1)
           return;
-        f.call$2(entry.value[0], A.convertNativeToDart_Dictionary(entry.value[1]));
+        t1 = entry.value[0];
+        t1.toString;
+        f.call$2(t1, A.convertNativeToDart_Dictionary(entry.value[1]));
       }
     },
     get$keys(receiver) {
@@ -13744,10 +14494,14 @@
       return keys;
     },
     get$length(receiver) {
-      return receiver.size;
+      var t1 = receiver.size;
+      t1.toString;
+      return t1;
     },
     get$isEmpty(receiver) {
-      return receiver.size === 0;
+      var t1 = receiver.size;
+      t1.toString;
+      return t1 === 0;
     },
     $indexSet(receiver, key, value) {
       throw A.wrapException(A.UnsupportedError$("Not supported"));
@@ -13758,21 +14512,28 @@
     call$2(k, v) {
       return B.JSArray_methods.add$1(this.keys, k);
     },
-    $signature: 5
+    $signature: 3
   };
   A.MidiOutputMap.prototype = {
+    containsKey$1(receiver, key) {
+      return A.convertNativeToDart_Dictionary(receiver.get(key)) != null;
+    },
     $index(receiver, key) {
       return A.convertNativeToDart_Dictionary(receiver.get(A._asString(key)));
     },
     forEach$1(receiver, f) {
-      var entries, entry;
+      var entries, entry, t1;
       type$.void_Function_String_dynamic._as(f);
       entries = receiver.entries();
       for (; true;) {
         entry = entries.next();
-        if (entry.done)
+        t1 = entry.done;
+        t1.toString;
+        if (t1)
           return;
-        f.call$2(entry.value[0], A.convertNativeToDart_Dictionary(entry.value[1]));
+        t1 = entry.value[0];
+        t1.toString;
+        f.call$2(t1, A.convertNativeToDart_Dictionary(entry.value[1]));
       }
     },
     get$keys(receiver) {
@@ -13781,10 +14542,14 @@
       return keys;
     },
     get$length(receiver) {
-      return receiver.size;
+      var t1 = receiver.size;
+      t1.toString;
+      return t1;
     },
     get$isEmpty(receiver) {
-      return receiver.size === 0;
+      var t1 = receiver.size;
+      t1.toString;
+      return t1 === 0;
     },
     $indexSet(receiver, key, value) {
       throw A.wrapException(A.UnsupportedError$("Not supported"));
@@ -13795,21 +14560,28 @@
     call$2(k, v) {
       return B.JSArray_methods.add$1(this.keys, k);
     },
-    $signature: 5
+    $signature: 3
   };
   A.MimeType.prototype = {$isMimeType: 1};
   A.MimeTypeArray.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.MimeType._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -13832,16 +14604,23 @@
   };
   A.NodeList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.Node._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -13863,16 +14642,23 @@
   };
   A.PluginArray.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.Plugin._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -13887,18 +14673,25 @@
     $isList: 1
   };
   A.RtcStatsReport.prototype = {
+    containsKey$1(receiver, key) {
+      return A.convertNativeToDart_Dictionary(receiver.get(key)) != null;
+    },
     $index(receiver, key) {
       return A.convertNativeToDart_Dictionary(receiver.get(A._asString(key)));
     },
     forEach$1(receiver, f) {
-      var entries, entry;
+      var entries, entry, t1;
       type$.void_Function_String_dynamic._as(f);
       entries = receiver.entries();
       for (; true;) {
         entry = entries.next();
-        if (entry.done)
+        t1 = entry.done;
+        t1.toString;
+        if (t1)
           return;
-        f.call$2(entry.value[0], A.convertNativeToDart_Dictionary(entry.value[1]));
+        t1 = entry.value[0];
+        t1.toString;
+        f.call$2(t1, A.convertNativeToDart_Dictionary(entry.value[1]));
       }
     },
     get$keys(receiver) {
@@ -13907,10 +14700,14 @@
       return keys;
     },
     get$length(receiver) {
-      return receiver.size;
+      var t1 = receiver.size;
+      t1.toString;
+      return t1;
     },
     get$isEmpty(receiver) {
-      return receiver.size === 0;
+      var t1 = receiver.size;
+      t1.toString;
+      return t1 === 0;
     },
     $indexSet(receiver, key, value) {
       throw A.wrapException(A.UnsupportedError$("Not supported"));
@@ -13921,7 +14718,7 @@
     call$2(k, v) {
       return B.JSArray_methods.add$1(this.keys, k);
     },
-    $signature: 5
+    $signature: 3
   };
   A.SelectElement.prototype = {
     get$length(receiver) {
@@ -13931,16 +14728,23 @@
   A.SourceBuffer.prototype = {$isSourceBuffer: 1};
   A.SourceBufferList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.SourceBuffer._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -13957,16 +14761,23 @@
   A.SpeechGrammar.prototype = {$isSpeechGrammar: 1};
   A.SpeechGrammarList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.SpeechGrammar._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -13987,6 +14798,9 @@
     $isSpeechRecognitionResult: 1
   };
   A.Storage.prototype = {
+    containsKey$1(receiver, key) {
+      return receiver.getItem(key) != null;
+    },
     $index(receiver, key) {
       return receiver.getItem(A._asString(key));
     },
@@ -14011,7 +14825,9 @@
       return keys;
     },
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     get$isEmpty(receiver) {
       return receiver.key(0) == null;
@@ -14022,23 +14838,30 @@
     call$2(k, v) {
       return B.JSArray_methods.add$1(this.keys, k);
     },
-    $signature: 30
+    $signature: 27
   };
   A.StyleSheet.prototype = {$isStyleSheet: 1};
   A.TextTrack.prototype = {$isTextTrack: 1};
   A.TextTrackCue.prototype = {$isTextTrackCue: 1};
   A.TextTrackCueList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.TextTrackCue._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14054,16 +14877,23 @@
   };
   A.TextTrackList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.TextTrack._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14079,22 +14909,31 @@
   };
   A.TimeRanges.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     }
   };
   A.Touch.prototype = {$isTouch: 1};
   A.TouchList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.Touch._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14115,7 +14954,9 @@
   };
   A.Url.prototype = {
     toString$0(receiver) {
-      return String(receiver);
+      var t1 = String(receiver);
+      t1.toString;
+      return t1;
     }
   };
   A.VideoTrackList.prototype = {
@@ -14125,16 +14966,23 @@
   };
   A._CssRuleList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.CssRule._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14225,16 +15073,21 @@
   };
   A._GamepadList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
       return receiver[index];
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.nullable_Gamepad._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14250,16 +15103,23 @@
   };
   A._NamedNodeMap.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.Node._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14275,16 +15135,23 @@
   };
   A._SpeechRecognitionResultList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.SpeechRecognitionResult._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14300,16 +15167,23 @@
   };
   A._StyleSheetList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1, t2;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver[index];
+      t1 = receiver.length;
+      t2 = index >>> 0 !== index || index >= t1;
+      t2.toString;
+      if (t2)
+        throw A.wrapException(A.IndexError$withLength(index, t1, receiver, null));
+      t1 = receiver[index];
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.StyleSheet._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14390,13 +15264,15 @@
   A.__SpeechRecognitionResultList_JavaScriptObject_ListMixin_ImmutableListMixin.prototype = {};
   A.__StyleSheetList_JavaScriptObject_ListMixin.prototype = {};
   A.__StyleSheetList_JavaScriptObject_ListMixin_ImmutableListMixin.prototype = {};
-  A._convertDataTree__convert.prototype = {
+  A.jsify__convert.prototype = {
     call$1(o) {
-      var convertedMap, t2, key, convertedList,
-        t1 = this._convertedObjects;
+      var t1, convertedMap, t2, key, convertedList;
+      if (A._noJsifyRequired(o))
+        return o;
+      t1 = this._convertedObjects;
       if (t1.containsKey$1(0, o))
         return t1.$index(0, o);
-      if (type$.Map_dynamic_dynamic._is(o)) {
+      if (type$.Map_of_nullable_Object_and_nullable_Object._is(o)) {
         convertedMap = {};
         t1.$indexSet(0, o, convertedMap);
         for (t1 = J.getInterceptor$x(o), t2 = J.get$iterator$ax(t1.get$keys(o)); t2.moveNext$0();) {
@@ -14404,7 +15280,7 @@
           convertedMap[key] = this.call$1(t1.$index(o, key));
         }
         return convertedMap;
-      } else if (type$.Iterable_dynamic._is(o)) {
+      } else if (type$.Iterable_nullable_Object._is(o)) {
         convertedList = [];
         t1.$indexSet(0, o, convertedList);
         B.JSArray_methods.addAll$1(convertedList, J.map$1$1$ax(o, this, type$.dynamic));
@@ -14412,13 +15288,13 @@
       } else
         return o;
     },
-    $signature: 20
+    $signature: 19
   };
   A.promiseToFuture_closure.prototype = {
     call$1(r) {
       return this.completer.complete$1(0, this.T._eval$1("0/?")._as(r));
     },
-    $signature: 3
+    $signature: 5
   };
   A.promiseToFuture_closure0.prototype = {
     call$1(e) {
@@ -14426,22 +15302,32 @@
         return this.completer.completeError$1(new A.NullRejectionException(e === undefined));
       return this.completer.completeError$1(e);
     },
-    $signature: 3
+    $signature: 5
   };
   A.dartify_convert.prototype = {
     call$1(o) {
-      var proto, t2, dartObject, originalKeys, dartKeys, i, jsKey, dartKey, l, $length,
-        t1 = this._convertedObjects;
+      var t1, millisSinceEpoch, proto, t2, dartObject, originalKeys, dartKeys, i, jsKey, dartKey, l, $length;
+      if (A._noDartifyRequired(o))
+        return o;
+      t1 = this._convertedObjects;
+      o.toString;
       if (t1.containsKey$1(0, o))
         return t1.$index(0, o);
-      if (o == null || A._isBool(o) || typeof o == "number" || typeof o == "string")
-        return o;
-      if (o instanceof Date)
-        return A.DateTime$fromMillisecondsSinceEpoch(o.getTime(), true);
+      if (o instanceof Date) {
+        millisSinceEpoch = o.getTime();
+        if (Math.abs(millisSinceEpoch) <= 864e13)
+          t1 = false;
+        else
+          t1 = true;
+        if (t1)
+          A.throwExpression(A.ArgumentError$("DateTime is outside valid range: " + millisSinceEpoch, null));
+        A.checkNotNullable(true, "isUtc", type$.bool);
+        return new A.DateTime(millisSinceEpoch, true);
+      }
       if (o instanceof RegExp)
         throw A.wrapException(A.ArgumentError$("structured clone of RegExp", null));
       if (typeof Promise != "undefined" && o instanceof Promise)
-        return A.promiseToFuture(o, type$.dynamic);
+        return A.promiseToFuture(o, type$.nullable_Object);
       proto = Object.getPrototypeOf(o);
       if (proto === Object.prototype || proto === null) {
         t2 = type$.nullable_Object;
@@ -14472,7 +15358,7 @@
       }
       return o;
     },
-    $signature: 20
+    $signature: 19
   };
   A.NullRejectionException.prototype = {
     toString$0(_) {
@@ -14483,16 +15369,24 @@
   A.Length.prototype = {$isLength: 1};
   A.LengthList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver.getItem(index);
+      t1 = receiver.length;
+      t1.toString;
+      t1 = index >>> 0 !== index || index >= t1;
+      t1.toString;
+      if (t1)
+        throw A.wrapException(A.IndexError$withLength(index, this.get$length(receiver), receiver, null));
+      t1 = receiver.getItem(index);
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.Length._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14506,16 +15400,24 @@
   A.Number.prototype = {$isNumber: 1};
   A.NumberList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver.getItem(index);
+      t1 = receiver.length;
+      t1.toString;
+      t1 = index >>> 0 !== index || index >= t1;
+      t1.toString;
+      if (t1)
+        throw A.wrapException(A.IndexError$withLength(index, this.get$length(receiver), receiver, null));
+      t1 = receiver.getItem(index);
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.Number._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14533,16 +15435,24 @@
   };
   A.StringList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver.getItem(index);
+      t1 = receiver.length;
+      t1.toString;
+      t1 = index >>> 0 !== index || index >= t1;
+      t1.toString;
+      if (t1)
+        throw A.wrapException(A.IndexError$withLength(index, this.get$length(receiver), receiver, null));
+      t1 = receiver.getItem(index);
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       A._asString(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14556,16 +15466,24 @@
   A.Transform.prototype = {$isTransform: 1};
   A.TransformList.prototype = {
     get$length(receiver) {
-      return receiver.length;
+      var t1 = receiver.length;
+      t1.toString;
+      return t1;
     },
     $index(receiver, index) {
+      var t1;
       A._asInt(index);
-      if (index >>> 0 !== index || index >= receiver.length)
-        throw A.wrapException(A.IndexError$(index, receiver, null, null, null));
-      return receiver.getItem(index);
+      t1 = receiver.length;
+      t1.toString;
+      t1 = index >>> 0 !== index || index >= t1;
+      t1.toString;
+      if (t1)
+        throw A.wrapException(A.IndexError$withLength(index, this.get$length(receiver), receiver, null));
+      t1 = receiver.getItem(index);
+      t1.toString;
+      return t1;
     },
     $indexSet(receiver, index, value) {
-      A._asInt(index);
       type$.Transform._as(value);
       throw A.wrapException(A.UnsupportedError$("Cannot assign element of immutable List."));
     },
@@ -14590,18 +15508,25 @@
     }
   };
   A.AudioParamMap.prototype = {
+    containsKey$1(receiver, key) {
+      return A.convertNativeToDart_Dictionary(receiver.get(key)) != null;
+    },
     $index(receiver, key) {
       return A.convertNativeToDart_Dictionary(receiver.get(A._asString(key)));
     },
     forEach$1(receiver, f) {
-      var entries, entry;
+      var entries, entry, t1;
       type$.void_Function_String_dynamic._as(f);
       entries = receiver.entries();
       for (; true;) {
         entry = entries.next();
-        if (entry.done)
+        t1 = entry.done;
+        t1.toString;
+        if (t1)
           return;
-        f.call$2(entry.value[0], A.convertNativeToDart_Dictionary(entry.value[1]));
+        t1 = entry.value[0];
+        t1.toString;
+        f.call$2(t1, A.convertNativeToDart_Dictionary(entry.value[1]));
       }
     },
     get$keys(receiver) {
@@ -14610,10 +15535,14 @@
       return keys;
     },
     get$length(receiver) {
-      return receiver.size;
+      var t1 = receiver.size;
+      t1.toString;
+      return t1;
     },
     get$isEmpty(receiver) {
-      return receiver.size === 0;
+      var t1 = receiver.size;
+      t1.toString;
+      return t1 === 0;
     },
     $indexSet(receiver, key, value) {
       throw A.wrapException(A.UnsupportedError$("Not supported"));
@@ -14624,7 +15553,7 @@
     call$2(k, v) {
       return B.JSArray_methods.add$1(this.keys, k);
     },
-    $signature: 5
+    $signature: 3
   };
   A.AudioTrackList.prototype = {
     get$length(receiver) {
@@ -14666,26 +15595,26 @@
     $signature: 2
   };
   A.Context.prototype = {
-    absolute$7(_, part1, part2, part3, part4, part5, part6, part7) {
+    absolute$15(_, part1, part2, part3, part4, part5, part6, part7, part8, part9, part10, part11, part12, part13, part14, part15) {
       var t1;
-      A._validateArgList("absolute", A._setArrayType([part1, part2, part3, part4, part5, part6, part7], type$.JSArray_nullable_String));
+      A._validateArgList("absolute", A._setArrayType([part1, part2, part3, part4, part5, part6, part7, part8, part9, part10, part11, part12, part13, part14, part15], type$.JSArray_nullable_String));
       t1 = this.style;
       t1 = t1.rootLength$1(part1) > 0 && !t1.isRootRelative$1(part1);
       if (t1)
         return part1;
       t1 = this._context$_current;
-      return this.join$8(0, t1 == null ? A.current() : t1, part1, part2, part3, part4, part5, part6, part7);
+      return this.join$16(0, t1 == null ? A.current() : t1, part1, part2, part3, part4, part5, part6, part7, part8, part9, part10, part11, part12, part13, part14, part15);
     },
     absolute$1($receiver, part1) {
-      return this.absolute$7($receiver, part1, null, null, null, null, null, null);
+      return this.absolute$15($receiver, part1, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
     },
-    join$8(_, part1, part2, part3, part4, part5, part6, part7, part8) {
-      var parts = A._setArrayType([part1, part2, part3, part4, part5, part6, part7, part8], type$.JSArray_nullable_String);
+    join$16(_, part1, part2, part3, part4, part5, part6, part7, part8, part9, part10, part11, part12, part13, part14, part15, part16) {
+      var parts = A._setArrayType([part1, part2, part3, part4, part5, part6, part7, part8, part9, part10, part11, part12, part13, part14, part15, part16], type$.JSArray_nullable_String);
       A._validateArgList("join", parts);
       return this.joinAll$1(new A.WhereTypeIterable(parts, type$.WhereTypeIterable_String));
     },
     join$2($receiver, part1, part2) {
-      return this.join$8($receiver, part1, part2, null, null, null, null, null, null);
+      return this.join$16($receiver, part1, part2, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
     },
     joinAll$1(parts) {
       var t1, t2, t3, needsSeparator, isAbsoluteAndNotRootRelative, t4, t5, parsed, path, t6;
@@ -14740,14 +15669,17 @@
       return parsed.toString$0(0);
     },
     _needsNormalization$1(path) {
-      var i, start, previous, t2, t3, previousPrevious, codeUnit, t4,
+      var t2, i, start, previous, t3, previousPrevious, codeUnit, t4,
         t1 = this.style,
         root = t1.rootLength$1(path);
       if (root !== 0) {
         if (t1 === $.$get$Style_windows())
-          for (i = 0; i < root; ++i)
-            if (B.JSString_methods._codeUnitAt$1(path, i) === 47)
+          for (t2 = path.length, i = 0; i < root; ++i) {
+            if (!(i < t2))
+              return A.ioore(path, i);
+            if (path.charCodeAt(i) === 47)
               return true;
+          }
         start = root;
         previous = 47;
       } else {
@@ -14755,7 +15687,9 @@
         previous = null;
       }
       for (t2 = new A.CodeUnits(path)._string, t3 = t2.length, i = start, previousPrevious = null; i < t3; ++i, previousPrevious = previous, previous = codeUnit) {
-        codeUnit = B.JSString_methods.codeUnitAt$1(t2, i);
+        if (!(i >= 0))
+          return A.ioore(t2, i);
+        codeUnit = t2.charCodeAt(i);
         if (t1.isSeparator$1(codeUnit)) {
           if (t1 === $.$get$Style_windows() && codeUnit === 47)
             return true;
@@ -14915,7 +15849,7 @@
       A._asStringQ(arg);
       return arg == null ? "null" : '"' + arg + '"';
     },
-    $signature: 33
+    $signature: 31
   };
   A.InternalStyle.prototype = {
     getRoot$1(path) {
@@ -14932,12 +15866,15 @@
       return t1;
     },
     relativePathToUri$1(path) {
-      var segments, _null = null,
+      var segments, t2, _null = null,
         t1 = path.length;
       if (t1 === 0)
         return A._Uri__Uri(_null, _null, _null, _null);
       segments = A.Context_Context(this).split$1(0, path);
-      if (this.isSeparator$1(B.JSString_methods.codeUnitAt$1(path, t1 - 1)))
+      t2 = t1 - 1;
+      if (!(t2 >= 0))
+        return A.ioore(path, t2);
+      if (this.isSeparator$1(path.charCodeAt(t2)))
         B.JSArray_methods.add$1(segments, "");
       return A._Uri__Uri(_null, _null, segments, _null);
     },
@@ -15049,11 +15986,27 @@
       return codeUnit === 47;
     },
     needsSeparator$1(path) {
-      var t1 = path.length;
-      return t1 !== 0 && B.JSString_methods.codeUnitAt$1(path, t1 - 1) !== 47;
+      var t2,
+        t1 = path.length;
+      if (t1 !== 0) {
+        t2 = t1 - 1;
+        if (!(t2 >= 0))
+          return A.ioore(path, t2);
+        t2 = path.charCodeAt(t2) !== 47;
+        t1 = t2;
+      } else
+        t1 = false;
+      return t1;
     },
     rootLength$2$withDrive(path, withDrive) {
-      if (path.length !== 0 && B.JSString_methods._codeUnitAt$1(path, 0) === 47)
+      var t1 = path.length;
+      if (t1 !== 0) {
+        if (0 >= t1)
+          return A.ioore(path, 0);
+        t1 = path.charCodeAt(0) === 47;
+      } else
+        t1 = false;
+      if (t1)
         return 1;
       return 0;
     },
@@ -15095,10 +16048,14 @@
       return codeUnit === 47;
     },
     needsSeparator$1(path) {
-      var t1 = path.length;
+      var t2,
+        t1 = path.length;
       if (t1 === 0)
         return false;
-      if (B.JSString_methods.codeUnitAt$1(path, t1 - 1) !== 47)
+      t2 = t1 - 1;
+      if (!(t2 >= 0))
+        return A.ioore(path, t2);
+      if (path.charCodeAt(t2) !== 47)
         return true;
       return B.JSString_methods.endsWith$1(path, "://") && this.rootLength$1(path) === t1;
     },
@@ -15107,10 +16064,12 @@
         t1 = path.length;
       if (t1 === 0)
         return 0;
-      if (B.JSString_methods._codeUnitAt$1(path, 0) === 47)
+      if (0 >= t1)
+        return A.ioore(path, 0);
+      if (path.charCodeAt(0) === 47)
         return 1;
       for (i = 0; i < t1; ++i) {
-        codeUnit = B.JSString_methods._codeUnitAt$1(path, i);
+        codeUnit = path.charCodeAt(i);
         if (codeUnit === 47)
           return 0;
         if (codeUnit === 58) {
@@ -15135,7 +16094,14 @@
       return this.rootLength$2$withDrive(path, false);
     },
     isRootRelative$1(path) {
-      return path.length !== 0 && B.JSString_methods._codeUnitAt$1(path, 0) === 47;
+      var t1 = path.length;
+      if (t1 !== 0) {
+        if (0 >= t1)
+          return A.ioore(path, 0);
+        t1 = path.charCodeAt(0) === 47;
+      } else
+        t1 = false;
+      return t1;
     },
     pathFromUri$1(uri) {
       return uri.toString$0(0);
@@ -15161,22 +16127,33 @@
       return codeUnit === 47 || codeUnit === 92;
     },
     needsSeparator$1(path) {
-      var t1 = path.length;
+      var t2,
+        t1 = path.length;
       if (t1 === 0)
         return false;
-      t1 = B.JSString_methods.codeUnitAt$1(path, t1 - 1);
-      return !(t1 === 47 || t1 === 92);
+      t2 = t1 - 1;
+      if (!(t2 >= 0))
+        return A.ioore(path, t2);
+      t2 = path.charCodeAt(t2);
+      return !(t2 === 47 || t2 === 92);
     },
     rootLength$2$withDrive(path, withDrive) {
       var t2, index,
         t1 = path.length;
       if (t1 === 0)
         return 0;
-      t2 = B.JSString_methods._codeUnitAt$1(path, 0);
-      if (t2 === 47)
+      if (0 >= t1)
+        return A.ioore(path, 0);
+      if (path.charCodeAt(0) === 47)
         return 1;
-      if (t2 === 92) {
-        if (t1 < 2 || B.JSString_methods._codeUnitAt$1(path, 1) !== 92)
+      if (path.charCodeAt(0) === 92) {
+        if (t1 >= 2) {
+          if (1 >= t1)
+            return A.ioore(path, 1);
+          t2 = path.charCodeAt(1) !== 92;
+        } else
+          t2 = true;
+        if (t2)
           return 1;
         index = B.JSString_methods.indexOf$2(path, "\\", 2);
         if (index > 0) {
@@ -15188,11 +16165,11 @@
       }
       if (t1 < 3)
         return 0;
-      if (!A.isAlphabetic(t2))
+      if (!A.isAlphabetic(path.charCodeAt(0)))
         return 0;
-      if (B.JSString_methods._codeUnitAt$1(path, 1) !== 58)
+      if (path.charCodeAt(1) !== 58)
         return 0;
-      t1 = B.JSString_methods._codeUnitAt$1(path, 2);
+      t1 = path.charCodeAt(2);
       if (!(t1 === 47 || t1 === 92))
         return 0;
       return 3;
@@ -15252,15 +16229,19 @@
       return upperCase1 >= 97 && upperCase1 <= 122;
     },
     pathsEqual$2(path1, path2) {
-      var t1, i;
+      var t1, t2, i;
       if (path1 === path2)
         return true;
       t1 = path1.length;
-      if (t1 !== path2.length)
+      t2 = path2.length;
+      if (t1 !== t2)
         return false;
-      for (i = 0; i < t1; ++i)
-        if (!this.codeUnitsEqual$2(B.JSString_methods._codeUnitAt$1(path1, i), B.JSString_methods._codeUnitAt$1(path2, i)))
+      for (i = 0; i < t1; ++i) {
+        if (!(i < t2))
+          return A.ioore(path2, i);
+        if (!this.codeUnitsEqual$2(path1.charCodeAt(i), path2.charCodeAt(i)))
           return false;
+      }
       return true;
     },
     get$name() {
@@ -15285,7 +16266,7 @@
     toString$0(_) {
       var t1 = this.traces,
         t2 = A._arrayInstanceType(t1);
-      return new A.MappedListIterable(t1, t2._eval$1("String(1)")._as(new A.Chain_toString_closure(new A.MappedListIterable(t1, t2._eval$1("int(1)")._as(new A.Chain_toString_closure0()), t2._eval$1("MappedListIterable<1,int>")).fold$1$2(0, 0, B.CONSTANT, type$.int))), t2._eval$1("MappedListIterable<1,String>")).join$1(0, string$.______);
+      return new A.MappedListIterable(t1, t2._eval$1("String(1)")._as(new A.Chain_toString_closure(new A.MappedListIterable(t1, t2._eval$1("int(1)")._as(new A.Chain_toString_closure0()), t2._eval$1("MappedListIterable<1,int>")).fold$1$2(0, 0, B.CONSTANT, type$.int))), t2._eval$1("MappedListIterable<1,String>")).join$1(0, string$.x3d_____);
     },
     $isStackTrace: 1
   };
@@ -15295,23 +16276,11 @@
     },
     $signature: 1
   };
-  A.Chain_Chain$parse_closure0.prototype = {
-    call$1(trace) {
-      return A.Trace$parseVM(A._asString(trace));
-    },
-    $signature: 18
-  };
-  A.Chain_Chain$parse_closure1.prototype = {
-    call$1(trace) {
-      return A.Trace$parseFriendly(A._asString(trace));
-    },
-    $signature: 18
-  };
   A.Chain_toTrace_closure.prototype = {
     call$1(trace) {
       return type$.Trace._as(trace).get$frames();
     },
-    $signature: 35
+    $signature: 32
   };
   A.Chain_toString_closure0.prototype = {
     call$1(trace) {
@@ -15319,14 +16288,14 @@
         t2 = A._arrayInstanceType(t1);
       return new A.MappedListIterable(t1, t2._eval$1("int(1)")._as(new A.Chain_toString__closure0()), t2._eval$1("MappedListIterable<1,int>")).fold$1$2(0, 0, B.CONSTANT, type$.int);
     },
-    $signature: 36
+    $signature: 33
   };
   A.Chain_toString__closure0.prototype = {
     call$1(frame) {
       type$.Frame._as(frame);
       return frame.get$location(frame).length;
     },
-    $signature: 17
+    $signature: 20
   };
   A.Chain_toString_closure.prototype = {
     call$1(trace) {
@@ -15334,14 +16303,14 @@
         t2 = A._arrayInstanceType(t1);
       return new A.MappedListIterable(t1, t2._eval$1("String(1)")._as(new A.Chain_toString__closure(this.longest)), t2._eval$1("MappedListIterable<1,String>")).join$0(0);
     },
-    $signature: 38
+    $signature: 35
   };
   A.Chain_toString__closure.prototype = {
     call$1(frame) {
       type$.Frame._as(frame);
       return B.JSString_methods.padRight$1(frame.get$location(frame), this.longest) + "  " + A.S(frame.get$member()) + "\n";
     },
-    $signature: 16
+    $signature: 21
   };
   A.Frame.prototype = {
     get$isCore() {
@@ -15399,7 +16368,7 @@
         return A.ioore(t1, 1);
       t2 = t1[1];
       t2.toString;
-      t3 = type$.Pattern._as($.$get$_asyncBody());
+      t3 = $.$get$_asyncBody();
       t2 = A.stringReplaceAllUnchecked(t2, t3, "<async>");
       member = A.stringReplaceAllUnchecked(t2, "<anonymous closure>", "<fn>");
       if (2 >= t1.length)
@@ -15488,7 +16457,7 @@
       columnMatch = t1[3];
       return new A.Frame(uri, line, columnMatch != null ? A.int_parse(columnMatch, _null) : _null, member);
     },
-    $signature: 41
+    $signature: 38
   };
   A.Frame_Frame$_parseFirefoxEval_closure.prototype = {
     call$0() {
@@ -15595,7 +16564,7 @@
       }
       if (uri.get$scheme() === "") {
         t2 = $.$get$context();
-        uri = t2.toUri$1(t2.absolute$7(0, t2.style.pathFromUri$1(A._parseUri(uri)), _null, _null, _null, _null, _null, _null));
+        uri = t2.toUri$1(t2.absolute$15(0, t2.style.pathFromUri$1(A._parseUri(uri)), _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null));
       }
       if (2 >= t1.length)
         return A.ioore(t1, 2);
@@ -15651,7 +16620,7 @@
     call$0() {
       return this.$this.get$_lazy_trace$_trace().get$terse();
     },
-    $signature: 15
+    $signature: 22
   };
   A.Trace.prototype = {
     get$terse() {
@@ -15693,7 +16662,7 @@
     call$0() {
       return A.Trace_Trace$parse(this.trace.toString$0(0));
     },
-    $signature: 15
+    $signature: 22
   };
   A.Trace__parseVM_closure.prototype = {
     call$1(line) {
@@ -15701,36 +16670,18 @@
     },
     $signature: 1
   };
-  A.Trace__parseVM_closure0.prototype = {
-    call$1(line) {
-      return A.Frame_Frame$parseVM(A._asString(line));
-    },
-    $signature: 4
-  };
   A.Trace$parseV8_closure.prototype = {
     call$1(line) {
       return !B.JSString_methods.startsWith$1(A._asString(line), $.$get$_v8TraceLine());
     },
     $signature: 1
   };
-  A.Trace$parseV8_closure0.prototype = {
-    call$1(line) {
-      return A.Frame_Frame$parseV8(A._asString(line));
-    },
-    $signature: 4
-  };
   A.Trace$parseJSCore_closure.prototype = {
     call$1(line) {
       return A._asString(line) !== "\tat ";
     },
     $signature: 1
   };
-  A.Trace$parseJSCore_closure0.prototype = {
-    call$1(line) {
-      return A.Frame_Frame$parseV8(A._asString(line));
-    },
-    $signature: 4
-  };
   A.Trace$parseFirefox_closure.prototype = {
     call$1(line) {
       A._asString(line);
@@ -15738,29 +16689,17 @@
     },
     $signature: 1
   };
-  A.Trace$parseFirefox_closure0.prototype = {
-    call$1(line) {
-      return A.Frame_Frame$parseFirefox(A._asString(line));
-    },
-    $signature: 4
-  };
   A.Trace$parseFriendly_closure.prototype = {
     call$1(line) {
       return !B.JSString_methods.startsWith$1(A._asString(line), "=====");
     },
     $signature: 1
   };
-  A.Trace$parseFriendly_closure0.prototype = {
-    call$1(line) {
-      return A.Frame_Frame$parseFriendly(A._asString(line));
-    },
-    $signature: 4
-  };
   A.Trace_terse_closure.prototype = {
     call$1(_) {
       return false;
     },
-    $signature: 13
+    $signature: 23
   };
   A.Trace_foldFrames_closure.prototype = {
     call$1(frame) {
@@ -15777,7 +16716,7 @@
         return false;
       return frame.get$line(frame) == null;
     },
-    $signature: 13
+    $signature: 23
   };
   A.Trace_foldFrames_closure0.prototype = {
     call$1(frame) {
@@ -15786,17 +16725,17 @@
       if (frame instanceof A.UnparsedFrame || !A.boolConversionCheck(this._box_0.predicate.call$1(frame)))
         return frame;
       t1 = frame.get$library();
-      t2 = type$.Pattern._as($.$get$_terseRegExp());
+      t2 = $.$get$_terseRegExp();
       return new A.Frame(A.Uri_parse(A.stringReplaceAllUnchecked(t1, t2, "")), null, null, frame.get$member());
     },
-    $signature: 45
+    $signature: 62
   };
   A.Trace_toString_closure0.prototype = {
     call$1(frame) {
       type$.Frame._as(frame);
       return frame.get$location(frame).length;
     },
-    $signature: 17
+    $signature: 20
   };
   A.Trace_toString_closure.prototype = {
     call$1(frame) {
@@ -15805,7 +16744,7 @@
         return frame.toString$0(0) + "\n";
       return B.JSString_methods.padRight$1(frame.get$location(frame), this.longest) + "  " + A.S(frame.get$member()) + "\n";
     },
-    $signature: 16
+    $signature: 21
   };
   A.UnparsedFrame.prototype = {
     toString$0(_) {
@@ -15983,7 +16922,7 @@
       t1._addStreamCompleter = null;
       t1.set$_addStreamSubscription(null);
     },
-    $signature: 8
+    $signature: 10
   };
   A._MultiChannel.prototype = {
     _MultiChannel$1(inner, $T) {
@@ -16020,13 +16959,13 @@
       if (_this._pendingIds.remove$1(0, id)) {
         t2 = _this._controllers.$index(0, id);
         t2.toString;
-        controller.__late_helper$_value = t2;
+        controller._value = t2;
       } else {
         t2 = _this._controllers;
         if (t2.containsKey$1(0, id) || _this._closedIds.contains$1(0, id))
           throw A.wrapException(A.ArgumentError$("A virtual channel with id " + id + " already exists.", null));
         else {
-          controller.__late_helper$_value = A.StreamChannelController$(true, _this.$ti._precomputed1);
+          controller._value = A.StreamChannelController$(true, _this.$ti._precomputed1);
           t2.$indexSet(0, id, controller._readLocal$0());
         }
       }
@@ -16072,8 +17011,10 @@
       t1.close$0(0);
       _this._innerStreamSubscription._source.cancel$0(0);
       _this._multi_channel$_inner = null;
-      for (t1 = _this._controllers, t2 = A.List_List$from(t1.get$values(t1), true, type$.dynamic), t3 = t2.length, _i = 0; _i < t3; ++_i) {
-        t4 = t2[_i].get$local().__GuaranteeChannel__sink_F;
+      for (t1 = _this._controllers, t2 = t1.get$values(t1), t2 = A.List_List$of(t2, false, A._instanceType(t2)._eval$1("Iterable.E")), t3 = t2.length, _i = 0; _i < t3; ++_i) {
+        t4 = t2[_i].__StreamChannelController__local_F;
+        t4 === $ && A.throwLateFieldNI("_local");
+        t4 = t4.__GuaranteeChannel__sink_F;
         t4 === $ && A.throwLateFieldNI("_sink");
         t4.close$0(0);
       }
@@ -16104,7 +17045,7 @@
       var t1, id, t2, t3, controller, t4;
       type$.List_dynamic._as(message);
       t1 = J.getInterceptor$asx(message);
-      id = A._asInt(t1.$index(message, 0));
+      id = B.JSNumber_methods.toInt$0(A._asNum(t1.$index(message, 0)));
       t2 = this.$this;
       if (t2._closedIds.contains$1(0, id))
         return;
@@ -16124,7 +17065,7 @@
         t1.close$0(0);
       }
     },
-    $signature: 46
+    $signature: 42
   };
   A._MultiChannel__closure.prototype = {
     call$0() {
@@ -16156,11 +17097,6 @@
   };
   A.VirtualChannel.prototype = {$isMultiChannel: 1};
   A.StreamChannelController.prototype = {
-    get$local() {
-      var t1 = this.__StreamChannelController__local_F;
-      t1 === $ && A.throwLateFieldNI("_local");
-      return t1;
-    },
     set$__StreamChannelController__local_F(__StreamChannelController__local_F) {
       this.__StreamChannelController__local_F = this.$ti._eval$1("StreamChannel<1>")._as(__StreamChannelController__local_F);
     },
@@ -16169,54 +17105,46 @@
     }
   };
   A.StreamChannelMixin.prototype = {$isStreamChannel: 1};
-  A.Window0.prototype = {};
-  A.Document0.prototype = {};
-  A.HTMLDocument.prototype = {};
-  A.Navigator0.prototype = {};
-  A.Element0.prototype = {};
-  A.HTMLElement.prototype = {};
-  A.HTMLBodyElement.prototype = {};
-  A.Node0.prototype = {};
-  A.EventTarget0.prototype = {};
-  A.Event0.prototype = {};
-  A.MessageEvent0.prototype = {};
-  A.Location0.prototype = {};
-  A.MessagePort0.prototype = {};
-  A.CSSStyleDeclaration.prototype = {};
-  A.HTMLScriptElement.prototype = {};
-  A.DomTokenList0.prototype = {};
-  A.HTMLIFrameElement.prototype = {};
-  A.WebSocket0.prototype = {};
-  A.MessageChannel0.prototype = {};
+  A.MessagePortExtension_get_postMessage_closure.prototype = {
+    call$1(message) {
+      var t2,
+        t1 = A._setArrayType([], type$.JSArray_Object);
+      if (message != null) {
+        t2 = A.jsify(message);
+        t1.push(t2 == null ? type$.Object._as(t2) : t2);
+      }
+      return A.callMethod(this._this, "postMessage", t1, type$.void);
+    },
+    $signature: 8
+  };
   A.Subscription.prototype = {};
-  A.TestRunner.prototype = {};
-  A._JSApi.prototype = {};
   A.main_closure.prototype = {
     call$0() {
-      var serverChannel = A._connectToServer(),
+      var play,
+        serverChannel = A._connectToServer(),
         t1 = serverChannel._mainController.__StreamChannelController__foreign_F;
       t1 === $ && A.throwLateFieldNI("_foreign");
       t1 = t1.__GuaranteeChannel__streamController_F;
       t1 === $ && A.throwLateFieldNI("_streamController");
       new A._ControllerStream(t1, A._instanceType(t1)._eval$1("_ControllerStream<1>")).listen$1(new A.main__closure(serverChannel));
       A.Timer_Timer$periodic(new A.Duration(1000000), new A.main__closure0(serverChannel));
-      t1 = type$.nullable_JavaScriptObject._as(self.document.querySelector("#play"));
-      t1.toString;
-      A.EventTargetExtension_addEventListener(t1, "click", A.allowInterop(new A.main__closure1(serverChannel), type$.void_Function_JavaScriptObject));
+      play = type$.nullable_JavaScriptObject._as(self.document.querySelector("#play"));
+      play.toString;
+      A.EventTargetExtension_addEventListener(play, "click", A.allowInterop(new A.main__closure1(serverChannel), type$.void_Function_JavaScriptObject));
       t1 = type$.void_Function;
-      self.dartTest = type$.JavaScriptObject._as({resume: A.allowInterop(new A.main__closure2(serverChannel), t1), restartCurrent: A.allowInterop(new A.main__closure3(serverChannel), t1)});
+      self.dartTest = {resume: A.allowInterop(new A.main__closure2(serverChannel), t1), restartCurrent: A.allowInterop(new A.main__closure3(serverChannel), t1)};
     },
     $signature: 2
   };
   A.main__closure.prototype = {
     call$1(message) {
-      var suiteChannel, t2, t3, t4,
+      var suiteChannel, t2, t3,
         _s7_ = "command",
         _s2_ = "id",
         t1 = J.getInterceptor$asx(message);
       if (J.$eq$(t1.$index(message, _s7_), "loadSuite")) {
-        suiteChannel = this.serverChannel.virtualChannel$1(A._asInt(t1.$index(message, "channel")));
-        t1 = suiteChannel.$ti._eval$1("StreamChannel<1>")._as(A._connectToIframe(A._asString(t1.$index(message, "url")), A._asInt(t1.$index(message, _s2_))));
+        suiteChannel = this.serverChannel.virtualChannel$1(B.JSNumber_methods.toInt$0(A._asNum(t1.$index(message, "channel"))));
+        t1 = suiteChannel.$ti._eval$1("StreamChannel<1>")._as(A._connectToIframe(A._asString(t1.$index(message, "url")), B.JSNumber_methods.toInt$0(A._asNum(t1.$index(message, _s2_)))));
         t2 = t1.__GuaranteeChannel__sink_F;
         t2 === $ && A.throwLateFieldNI("_sink");
         suiteChannel.stream.pipe$1(t2);
@@ -16233,23 +17161,14 @@
         if (t3._as(t2.parentNode) != null)
           type$.JavaScriptObject._as(t3._as(t2.parentNode).removeChild(t2));
         t2 = $._subscriptions.remove$1(0, t1.$index(message, _s2_));
-        t2.toString;
-        t2 = J.get$iterator$ax(t2);
-        for (; t2.moveNext$0();)
-          t2.get$current(t2).cancel$0(0);
+        if (t2 != null)
+          J.cancel$0$z(t2);
         t1 = $._domSubscriptions.remove$1(0, t1.$index(message, _s2_));
-        t1.toString;
-        t1 = J.get$iterator$ax(t1);
-        t2 = type$.JSArray_Object;
-        for (; t1.moveNext$0();) {
-          t3 = t1.get$current(t1);
-          t4 = t3.target;
-          t3 = A._setArrayType([t3.type, t3.listener], t2);
-          t4.removeEventListener.apply(t4, t3);
-        }
+        if (t1 != null)
+          A.EventTargetExtension_removeEventListener(t1.target, t1.type, t1.listener);
       }
     },
-    $signature: 3
+    $signature: 5
   };
   A.main__closure0.prototype = {
     call$1(_) {
@@ -16262,7 +17181,7 @@
       t2 = type$.String;
       return t1.add$1(0, A.LinkedHashMap_LinkedHashMap$_literal(["command", "ping"], t2, t2));
     },
-    $signature: 47
+    $signature: 43
   };
   A.main__closure1.prototype = {
     call$1(_) {
@@ -16322,7 +17241,7 @@
       else
         toZone.call$1(line);
     },
-    $signature: 10
+    $signature: 11
   };
   A._connectToServer_closure.prototype = {
     call$1(message) {
@@ -16338,37 +17257,132 @@
   };
   A._connectToServer_closure0.prototype = {
     call$1(message) {
-      return A.callMethod(this.webSocket, "send", [B.C_JsonCodec.encode$2$toEncodable(message, null)], type$.void);
+      return this.webSocket.send(B.C_JsonCodec.encode$2$toEncodable(message, null));
     },
-    $signature: 3
+    $signature: 5
   };
   A._connectToIframe_closure.prototype = {
     call$1($event) {
-      var t2, t3, _this = this,
+      var $location, t2, t3, _0_0, _0_6, _0_11, _0_15, port, t4, t5, data, _this = this, _null = null, _s6_ = "_local",
+        _s17_ = "_streamController",
         t1 = type$.JavaScriptObject;
       t1._as($event);
       if (A._asString($event.origin) !== A._asString(t1._as(self.window.location).origin))
         return;
+      $location = $event.source.location;
+      if ($location == null)
+        return;
       t2 = _this.iframe;
-      if (!J.$eq$(J.$index$asx(A.dartify($event.data), "href"), A._asStringQ(t2.src)))
+      if (!J.$eq$($location.href, A._asStringQ(t2.src)))
         return;
       $event.stopPropagation();
-      if (J.$eq$(J.$index$asx(A.dartify($event.data), "ready"), true)) {
-        t3 = _this.channel;
-        t1._as(t3.port2).start();
-        type$.Object._as(t2.contentWindow).postMessage("port", A._asString(t1._as(self.window.location).origin), A._setArrayType([t1._as(t3.port2)], type$.JSArray_JavaScriptObject));
-        _this.readyCompleter.complete$0(0);
-      } else if (J.$eq$(J.$index$asx(A.dartify($event.data), "exception"), true)) {
-        t1 = _this.controller.__StreamChannelController__local_F;
-        t1 === $ && A.throwLateFieldNI("_local");
-        t1 = t1.__GuaranteeChannel__sink_F;
-        t1 === $ && A.throwLateFieldNI("_sink");
-        t1.add$1(0, J.$index$asx(A.dartify($event.data), "data"));
+      t3 = _this.windowSubscription._readLocal$0();
+      A.EventTargetExtension_removeEventListener(t3.target, t3.type, t3.listener);
+      $label0$0: {
+        _0_0 = A.dartify($event.data);
+        _0_6 = A._InitializedCell$named("#0#6", new A._connectToIframe__closure(_0_0));
+        _0_11 = A._InitializedCell$named("#0#11", new A._connectToIframe__closure0(_0_0));
+        _0_15 = A._InitializedCell$named("#0#15", new A._connectToIframe__closure1(_0_0));
+        if ("port" === _0_0) {
+          t1 = J.cast$1$0$ax(type$.List_dynamic._as($event.ports), t1);
+          port = t1.get$first(t1);
+          t1 = _this.id;
+          t2 = _this.controller;
+          $._domSubscriptions.$indexSet(0, t1, A.Subscription$(port, "message", A.allowInterop(new A._connectToIframe__closure2(t2), type$.void_Function_JavaScriptObject)));
+          port.start();
+          t2 = t2.__StreamChannelController__local_F;
+          t2 === $ && A.throwLateFieldNI(_s6_);
+          t2 = t2.__GuaranteeChannel__streamController_F;
+          t2 === $ && A.throwLateFieldNI(_s17_);
+          $._subscriptions.$indexSet(0, t1, new A._ControllerStream(t2, A._instanceType(t2)._eval$1("_ControllerStream<1>")).listen$1(A.MessagePortExtension_get_postMessage(port)));
+          break $label0$0;
+        }
+        t3 = type$.Map_dynamic_dynamic._is(_0_0);
+        if (t3) {
+          if (_0_6._readFinal$0() == null)
+            t4 = J.containsKey$1$x(_0_0, "ready");
+          else
+            t4 = true;
+          t4 = t4 && true === _0_6._readFinal$0();
+        } else
+          t4 = false;
+        if (t4) {
+          t3 = A._callConstructor("MessageChannel", A._setArrayType([], type$.JSArray_Object));
+          t3.toString;
+          t1._as(t3);
+          t4 = _this.id;
+          t5 = _this.controller;
+          $._domSubscriptions.$indexSet(0, t4, A.Subscription$(t1._as(t3.port1), "message", A.allowInterop(new A._connectToIframe__closure3(t5), type$.void_Function_JavaScriptObject)));
+          t5 = t5.__StreamChannelController__local_F;
+          t5 === $ && A.throwLateFieldNI(_s6_);
+          t5 = t5.__GuaranteeChannel__streamController_F;
+          t5 === $ && A.throwLateFieldNI(_s17_);
+          $._subscriptions.$indexSet(0, t4, new A._ControllerStream(t5, A._instanceType(t5)._eval$1("_ControllerStream<1>")).listen$1(A.MessagePortExtension_get_postMessage(t1._as(t3.port1))));
+          t1._as(t3.port2).start();
+          t1._as(t3.port1).start();
+          type$.Object._as(t2.contentWindow).postMessage("port", A._asString(t1._as(self.window.location).origin), A._setArrayType([t1._as(t3.port2)], type$.JSArray_JavaScriptObject));
+          break $label0$0;
+        }
+        if (t3) {
+          if (_0_11._readFinal$0() == null)
+            t1 = J.containsKey$1$x(_0_0, "exception");
+          else
+            t1 = true;
+          if (t1)
+            if (true === _0_11._readFinal$0()) {
+              if (_0_15._readFinal$0() == null)
+                t1 = J.containsKey$1$x(_0_0, "data");
+              else
+                t1 = true;
+              if (t1) {
+                data = _0_15._readFinal$0();
+                t1 = true;
+              } else {
+                data = _null;
+                t1 = false;
+              }
+            } else {
+              data = _null;
+              t1 = false;
+            }
+          else {
+            data = _null;
+            t1 = false;
+          }
+        } else {
+          data = _null;
+          t1 = false;
+        }
+        if (t1) {
+          t1 = _this.controller.__StreamChannelController__local_F;
+          t1 === $ && A.throwLateFieldNI(_s6_);
+          t1 = t1.__GuaranteeChannel__sink_F;
+          t1 === $ && A.throwLateFieldNI("_sink");
+          t1.add$1(0, data);
+        }
       }
     },
     $signature: 7
   };
-  A._connectToIframe_closure0.prototype = {
+  A._connectToIframe__closure2.prototype = {
+    call$1($event) {
+      var t1;
+      type$.JavaScriptObject._as($event);
+      t1 = this.controller.__StreamChannelController__local_F;
+      t1 === $ && A.throwLateFieldNI("_local");
+      t1 = t1.__GuaranteeChannel__sink_F;
+      t1 === $ && A.throwLateFieldNI("_sink");
+      t1.add$1(0, A.dartify($event.data));
+    },
+    $signature: 7
+  };
+  A._connectToIframe__closure.prototype = {
+    call$0() {
+      return J.$index$asx(type$.Map_dynamic_dynamic._as(this._0_0), "ready");
+    },
+    $signature: 4
+  };
+  A._connectToIframe__closure3.prototype = {
     call$1($event) {
       var t1;
       type$.JavaScriptObject._as($event);
@@ -16380,38 +17394,17 @@
     },
     $signature: 7
   };
-  A._connectToIframe_closure1.prototype = {
-    call$1(message) {
-      var $async$goto = 0,
-        $async$completer = A._makeAsyncAwaitCompleter(type$.void),
-        $async$self = this, t1, t2, t3;
-      var $async$call$1 = A._wrapJsFunctionForAsync(function($async$errorCode, $async$result) {
-        if ($async$errorCode === 1)
-          return A._asyncRethrow($async$result, $async$completer);
-        while (true)
-          switch ($async$goto) {
-            case 0:
-              // Function start
-              $async$goto = 2;
-              return A._asyncAwait($async$self.readyCompleter.future, $async$call$1);
-            case 2:
-              // returning from await.
-              t1 = type$.JavaScriptObject._as($async$self.channel.port1);
-              t2 = A._setArrayType([], type$.JSArray_Object);
-              if (message != null) {
-                if (!type$.Map_dynamic_dynamic._is(message) && !type$.Iterable_dynamic._is(message))
-                  A.throwExpression(A.ArgumentError$("object must be a Map or Iterable", null));
-                t3 = A._convertDataTree(message);
-                t2.push(t3);
-              }
-              A.callMethod(t1, "postMessage", t2, type$.void);
-              // implicit return
-              return A._asyncReturn(null, $async$completer);
-          }
-      });
-      return A._asyncStartSync($async$call$1, $async$completer);
+  A._connectToIframe__closure0.prototype = {
+    call$0() {
+      return J.$index$asx(type$.Map_dynamic_dynamic._as(this._0_0), "exception");
     },
-    $signature: 49
+    $signature: 4
+  };
+  A._connectToIframe__closure1.prototype = {
+    call$0() {
+      return J.$index$asx(type$.Map_dynamic_dynamic._as(this._0_0), "data");
+    },
+    $signature: 4
   };
   (function aliases() {
     var _ = J.Interceptor.prototype;
@@ -16431,106 +17424,114 @@
       _instance_2_u = hunkHelpers._instance_2u,
       _instance_1_i = hunkHelpers._instance_1i,
       _instance_0_u = hunkHelpers._instance_0u;
-    _instance_1_u(A.CastStreamSubscription.prototype, "get$__internal$_onData", "__internal$_onData$1", 12);
-    _static_1(A, "async__AsyncRun__scheduleImmediateJsOverride$closure", "_AsyncRun__scheduleImmediateJsOverride", 9);
-    _static_1(A, "async__AsyncRun__scheduleImmediateWithSetImmediate$closure", "_AsyncRun__scheduleImmediateWithSetImmediate", 9);
-    _static_1(A, "async__AsyncRun__scheduleImmediateWithTimer$closure", "_AsyncRun__scheduleImmediateWithTimer", 9);
+    _instance_1_u(A.CastStreamSubscription.prototype, "get$__internal$_onData", "__internal$_onData$1", 8);
+    _static_1(A, "async__AsyncRun__scheduleImmediateJsOverride$closure", "_AsyncRun__scheduleImmediateJsOverride", 13);
+    _static_1(A, "async__AsyncRun__scheduleImmediateWithSetImmediate$closure", "_AsyncRun__scheduleImmediateWithSetImmediate", 13);
+    _static_1(A, "async__AsyncRun__scheduleImmediateWithTimer$closure", "_AsyncRun__scheduleImmediateWithTimer", 13);
     _static_0(A, "async___startMicrotaskLoop$closure", "_startMicrotaskLoop", 0);
-    _static_1(A, "async___nullDataHandler$closure", "_nullDataHandler", 3);
-    _static_2(A, "async___nullErrorHandler$closure", "_nullErrorHandler", 10);
+    _static_1(A, "async___nullDataHandler$closure", "_nullDataHandler", 5);
+    _static_2(A, "async___nullErrorHandler$closure", "_nullErrorHandler", 11);
     _static_0(A, "async___nullDoneHandler$closure", "_nullDoneHandler", 0);
-    _static(A, "async___rootHandleUncaughtError$closure", 5, null, ["call$5"], ["_rootHandleUncaughtError"], 51, 0);
+    _static(A, "async___rootHandleUncaughtError$closure", 5, null, ["call$5"], ["_rootHandleUncaughtError"], 46, 0);
     _static(A, "async___rootRun$closure", 4, null, ["call$1$4", "call$4"], ["_rootRun", function($self, $parent, zone, f) {
       return A._rootRun($self, $parent, zone, f, type$.dynamic);
-    }], 52, 1);
+    }], 47, 1);
     _static(A, "async___rootRunUnary$closure", 5, null, ["call$2$5", "call$5"], ["_rootRunUnary", function($self, $parent, zone, f, arg) {
       return A._rootRunUnary($self, $parent, zone, f, arg, type$.dynamic, type$.dynamic);
-    }], 53, 1);
+    }], 48, 1);
     _static(A, "async___rootRunBinary$closure", 6, null, ["call$3$6", "call$6"], ["_rootRunBinary", function($self, $parent, zone, f, arg1, arg2) {
       return A._rootRunBinary($self, $parent, zone, f, arg1, arg2, type$.dynamic, type$.dynamic, type$.dynamic);
-    }], 54, 1);
+    }], 49, 1);
     _static(A, "async___rootRegisterCallback$closure", 4, null, ["call$1$4", "call$4"], ["_rootRegisterCallback", function($self, $parent, zone, f) {
       return A._rootRegisterCallback($self, $parent, zone, f, type$.dynamic);
-    }], 55, 0);
+    }], 50, 0);
     _static(A, "async___rootRegisterUnaryCallback$closure", 4, null, ["call$2$4", "call$4"], ["_rootRegisterUnaryCallback", function($self, $parent, zone, f) {
       return A._rootRegisterUnaryCallback($self, $parent, zone, f, type$.dynamic, type$.dynamic);
-    }], 56, 0);
+    }], 51, 0);
     _static(A, "async___rootRegisterBinaryCallback$closure", 4, null, ["call$3$4", "call$4"], ["_rootRegisterBinaryCallback", function($self, $parent, zone, f) {
       return A._rootRegisterBinaryCallback($self, $parent, zone, f, type$.dynamic, type$.dynamic, type$.dynamic);
-    }], 57, 0);
-    _static(A, "async___rootErrorCallback$closure", 5, null, ["call$5"], ["_rootErrorCallback"], 58, 0);
-    _static(A, "async___rootScheduleMicrotask$closure", 4, null, ["call$4"], ["_rootScheduleMicrotask"], 59, 0);
-    _static(A, "async___rootCreateTimer$closure", 5, null, ["call$5"], ["_rootCreateTimer"], 60, 0);
-    _static(A, "async___rootCreatePeriodicTimer$closure", 5, null, ["call$5"], ["_rootCreatePeriodicTimer"], 61, 0);
-    _static(A, "async___rootPrint$closure", 4, null, ["call$4"], ["_rootPrint"], 62, 0);
-    _static_1(A, "async___printToZone$closure", "_printToZone", 63);
-    _static(A, "async___rootFork$closure", 5, null, ["call$5"], ["_rootFork"], 64, 0);
+    }], 52, 0);
+    _static(A, "async___rootErrorCallback$closure", 5, null, ["call$5"], ["_rootErrorCallback"], 53, 0);
+    _static(A, "async___rootScheduleMicrotask$closure", 4, null, ["call$4"], ["_rootScheduleMicrotask"], 54, 0);
+    _static(A, "async___rootCreateTimer$closure", 5, null, ["call$5"], ["_rootCreateTimer"], 55, 0);
+    _static(A, "async___rootCreatePeriodicTimer$closure", 5, null, ["call$5"], ["_rootCreatePeriodicTimer"], 56, 0);
+    _static(A, "async___rootPrint$closure", 4, null, ["call$4"], ["_rootPrint"], 57, 0);
+    _static_1(A, "async___printToZone$closure", "_printToZone", 58);
+    _static(A, "async___rootFork$closure", 5, null, ["call$5"], ["_rootFork"], 59, 0);
     _instance(A._SyncCompleter.prototype, "get$complete", 1, 0, function() {
       return [null];
-    }, ["call$1", "call$0"], ["complete$1", "complete$0"], 39, 0, 0);
-    _instance_2_u(A._Future.prototype, "get$_completeError", "_completeError$2", 10);
+    }, ["call$1", "call$0"], ["complete$1", "complete$0"], 44, 0, 0);
+    _instance_2_u(A._Future.prototype, "get$_completeError", "_completeError$2", 11);
     var _;
-    _instance_1_i(_ = A._StreamController.prototype, "get$add", "add$1", 12);
+    _instance_1_i(_ = A._StreamController.prototype, "get$add", "add$1", 8);
     _instance(_, "get$addError", 0, 1, function() {
       return [null];
-    }, ["call$2", "call$1"], ["addError$2", "addError$1"], 11, 0, 0);
-    _instance_1_i(A._StreamSinkWrapper.prototype, "get$add", "add$1", 12);
+    }, ["call$2", "call$1"], ["addError$2", "addError$1"], 12, 0, 0);
+    _instance_1_i(A._StreamSinkWrapper.prototype, "get$add", "add$1", 8);
     _instance_0_u(A._DoneStreamSubscription.prototype, "get$_sendDone", "_sendDone$0", 0);
-    _static_1(A, "convert___defaultToEncodable$closure", "_defaultToEncodable", 14);
-    _static_1(A, "core_Uri_decodeComponent$closure", "Uri_decodeComponent", 23);
+    _static_1(A, "convert___defaultToEncodable$closure", "_defaultToEncodable", 15);
+    _static_1(A, "core_Uri_decodeComponent$closure", "Uri_decodeComponent", 17);
+    _static_1(A, "frame_Frame___parseVM_tearOff$closure", "Frame___parseVM_tearOff", 9);
+    _static_1(A, "frame_Frame___parseV8_tearOff$closure", "Frame___parseV8_tearOff", 9);
+    _static_1(A, "frame_Frame___parseFirefox_tearOff$closure", "Frame___parseFirefox_tearOff", 9);
+    _static_1(A, "frame_Frame___parseFriendly_tearOff$closure", "Frame___parseFriendly_tearOff", 9);
+    _static_1(A, "trace_Trace___parseVM_tearOff$closure", "Trace___parseVM_tearOff", 14);
+    _static_1(A, "trace_Trace___parseFriendly_tearOff$closure", "Trace___parseFriendly_tearOff", 14);
     _instance(_ = A._GuaranteeSink.prototype, "get$addError", 0, 1, function() {
       return [null];
-    }, ["call$2", "call$1"], ["addError$2", "addError$1"], 11, 0, 0);
+    }, ["call$2", "call$1"], ["addError$2", "addError$1"], 12, 0, 0);
     _instance(_, "get$_addError", 0, 1, function() {
       return [null];
-    }, ["call$2", "call$1"], ["_addError$2", "_addError$1"], 11, 0, 0);
+    }, ["call$2", "call$1"], ["_addError$2", "_addError$1"], 12, 0, 0);
     _instance_0_u(A._MultiChannel.prototype, "get$_closeInnerChannel", "_closeInnerChannel$0", 0);
     _static(A, "math__max$closure", 2, null, ["call$1$2", "call$2"], ["max", function(a, b) {
       return A.max(a, b, type$.num);
-    }], 43, 0);
+    }], 41, 0);
   })();
   (function inheritance() {
     var _mixin = hunkHelpers.mixin,
       _inherit = hunkHelpers.inherit,
       _inheritMany = hunkHelpers.inheritMany;
     _inherit(A.Object, null);
-    _inheritMany(A.Object, [A.JS_CONST, J.Interceptor, J.ArrayIterator, A.Stream, A.CastStreamSubscription, A.Error, A._ListBase_Object_ListMixin, A.Closure, A.SentinelValue, A.Iterable, A.ListIterator, A.Iterator, A.ExpandIterator, A.EmptyIterator, A.WhereTypeIterator, A.FixedLengthListMixin, A.UnmodifiableListMixin, A.Symbol, A.MapView, A.ConstantMap, A.JSInvocationMirror, A.TypeErrorDecoder, A.NullThrownFromJavaScriptException, A.ExceptionAndStackTrace, A._StackTrace, A._Required, A.MapMixin, A.LinkedHashMapCell, A.LinkedHashMapKeyIterator, A.JSSyntaxRegExp, A._MatchImplementation, A._AllMatchesIterator, A.StringMatch, A._StringAllMatchesIterator, A._Cell, A.Rti, A._FunctionParameters, A._Type, A._TimerImpl, A._AsyncAwaitCompleter, A.AsyncError, A._Completer, A._FutureListener, A._Future, A._AsyncCallbackEntry, A.StreamTransformerBase, A._StreamController, A._SyncStreamControllerDispatch, A._BufferingStreamSubscription, A._StreamSinkWrapper, A._DelayedEvent, A._DelayedDone, A._PendingEvents, A._DoneStreamSubscription, A._StreamIterator, A._ZoneFunction, A._ZoneSpecification, A._ZoneDelegate, A._Zone, A._HashMapKeyIterator, A.__SetBase_Object_SetMixin, A._LinkedHashSetCell, A._LinkedHashSetIterator, A.ListMixin, A._UnmodifiableMapMixin, A.SetMixin, A.Codec, A._JsonStringifier, A._Utf8Encoder, A._Utf8Decoder, A.DateTime, A.Duration, A.OutOfMemoryError, A.StackOverflowError, A._Exception, A.FormatException, A.Null, A._StringStackTrace, A.StringBuffer, A._Uri, A.UriData, A._SimpleUri, A.CssStyleDeclarationBase, A.ImmutableListMixin, A.FixedSizeListIterator, A.NullRejectionException, A.NullStreamSink, A.Context, A.Style, A.ParsedPath, A.PathException, A.Chain, A.Frame, A.LazyTrace, A.Trace, A.UnparsedFrame, A.StreamChannelMixin, A._GuaranteeSink, A.StreamChannelController, A.Subscription]);
-    _inheritMany(J.Interceptor, [J.JSBool, J.JSNull, J.JavaScriptObject, J.JSArray, J.JSNumber, J.JSString, A.NativeTypedData]);
-    _inheritMany(J.JavaScriptObject, [J.LegacyJavaScriptObject, A.EventTarget, A.AccessibleNodeList, A.Blob, A.CssTransformComponent, A.CssRule, A._CssStyleDeclaration_JavaScriptObject_CssStyleDeclarationBase, A.CssStyleValue, A.DataTransferItemList, A.DomException, A._DomRectList_JavaScriptObject_ListMixin, A.DomRectReadOnly, A._DomStringList_JavaScriptObject_ListMixin, A.DomTokenList, A._FileList_JavaScriptObject_ListMixin, A.Gamepad, A.History, A._HtmlCollection_JavaScriptObject_ListMixin, A.Location, A.MediaList, A._MidiInputMap_JavaScriptObject_MapMixin, A._MidiOutputMap_JavaScriptObject_MapMixin, A.MimeType, A._MimeTypeArray_JavaScriptObject_ListMixin, A._NodeList_JavaScriptObject_ListMixin, A.Plugin, A._PluginArray_JavaScriptObject_ListMixin, A._RtcStatsReport_JavaScriptObject_MapMixin, A.SpeechGrammar, A._SpeechGrammarList_JavaScriptObject_ListMixin, A.SpeechRecognitionResult, A._Storage_JavaScriptObject_MapMixin, A.StyleSheet, A._TextTrackCueList_JavaScriptObject_ListMixin, A.TimeRanges, A.Touch, A._TouchList_JavaScriptObject_ListMixin, A.TrackDefaultList, A.Url, A.__CssRuleList_JavaScriptObject_ListMixin, A.__GamepadList_JavaScriptObject_ListMixin, A.__NamedNodeMap_JavaScriptObject_ListMixin, A.__SpeechRecognitionResultList_JavaScriptObject_ListMixin, A.__StyleSheetList_JavaScriptObject_ListMixin, A.Length, A._LengthList_JavaScriptObject_ListMixin, A.Number, A._NumberList_JavaScriptObject_ListMixin, A.PointList, A._StringList_JavaScriptObject_ListMixin, A.Transform, A._TransformList_JavaScriptObject_ListMixin, A.AudioBuffer, A._AudioParamMap_JavaScriptObject_MapMixin]);
-    _inheritMany(J.LegacyJavaScriptObject, [J.PlainJavaScriptObject, J.UnknownJavaScriptObject, J.JavaScriptFunction, A.EventTarget0, A.Navigator0, A.Event0, A.Location0, A.CSSStyleDeclaration, A.DomTokenList0, A.MessageChannel0, A.TestRunner, A._JSApi]);
+    _inheritMany(A.Object, [A.JS_CONST, J.Interceptor, J.ArrayIterator, A.Stream, A.CastStreamSubscription, A.Iterable, A.CastIterator, A.Error, A.ListBase, A.Closure, A.SentinelValue, A.ListIterator, A.MappedIterator, A.WhereIterator, A.ExpandIterator, A.TakeIterator, A.SkipIterator, A.SkipWhileIterator, A.EmptyIterator, A.WhereTypeIterator, A.FixedLengthListMixin, A.UnmodifiableListMixin, A.Symbol, A.MapView, A.ConstantMap, A._KeysOrValuesOrElementsIterator, A.JSInvocationMirror, A.TypeErrorDecoder, A.NullThrownFromJavaScriptException, A._StackTrace, A._Required, A.MapBase, A.LinkedHashMapCell, A.LinkedHashMapKeyIterator, A.JSSyntaxRegExp, A._MatchImplementation, A._AllMatchesIterator, A.StringMatch, A._StringAllMatchesIterator, A._Cell, A._InitializedCell, A.Rti, A._FunctionParameters, A._Type, A._TimerImpl, A.AsyncError, A._Completer, A._FutureListener, A._Future, A._AsyncCallbackEntry, A._StreamController, A._SyncStreamControllerDispatch, A._BufferingStreamSubscription, A._StreamSinkWrapper, A._DelayedEvent, A._DelayedDone, A._PendingEvents, A._DoneStreamSubscription, A._ZoneFunction, A._ZoneSpecification, A._ZoneDelegate, A._Zone, A._HashMapKeyIterator, A.SetBase, A._LinkedHashSetCell, A._LinkedHashSetIterator, A._UnmodifiableMapMixin, A.Codec, A.Converter, A._JsonStringifier, A._Utf8Encoder, A._Utf8Decoder, A.DateTime, A.Duration, A.OutOfMemoryError, A.StackOverflowError, A._Exception, A.FormatException, A.Null, A._StringStackTrace, A.StringBuffer, A._Uri, A.UriData, A._SimpleUri, A.CssStyleDeclarationBase, A.ImmutableListMixin, A.FixedSizeListIterator, A.NullRejectionException, A.NullStreamSink, A.Context, A.Style, A.ParsedPath, A.PathException, A.Chain, A.Frame, A.LazyTrace, A.Trace, A.UnparsedFrame, A.StreamChannelMixin, A._GuaranteeSink, A.StreamChannelController, A.Subscription]);
+    _inheritMany(J.Interceptor, [J.JSBool, J.JSNull, J.JavaScriptObject, J.JSNumber, J.JSString]);
+    _inheritMany(J.JavaScriptObject, [J.LegacyJavaScriptObject, J.JSArray, A.NativeByteBuffer, A.NativeTypedData, A.EventTarget, A.AccessibleNodeList, A.Blob, A.CssTransformComponent, A.CssRule, A._CssStyleDeclaration_JavaScriptObject_CssStyleDeclarationBase, A.CssStyleValue, A.DataTransferItemList, A.DomException, A._DomRectList_JavaScriptObject_ListMixin, A.DomRectReadOnly, A._DomStringList_JavaScriptObject_ListMixin, A.DomTokenList, A._FileList_JavaScriptObject_ListMixin, A.Gamepad, A.History, A._HtmlCollection_JavaScriptObject_ListMixin, A.Location, A.MediaList, A._MidiInputMap_JavaScriptObject_MapMixin, A._MidiOutputMap_JavaScriptObject_MapMixin, A.MimeType, A._MimeTypeArray_JavaScriptObject_ListMixin, A._NodeList_JavaScriptObject_ListMixin, A.Plugin, A._PluginArray_JavaScriptObject_ListMixin, A._RtcStatsReport_JavaScriptObject_MapMixin, A.SpeechGrammar, A._SpeechGrammarList_JavaScriptObject_ListMixin, A.SpeechRecognitionResult, A._Storage_JavaScriptObject_MapMixin, A.StyleSheet, A._TextTrackCueList_JavaScriptObject_ListMixin, A.TimeRanges, A.Touch, A._TouchList_JavaScriptObject_ListMixin, A.TrackDefaultList, A.Url, A.__CssRuleList_JavaScriptObject_ListMixin, A.__GamepadList_JavaScriptObject_ListMixin, A.__NamedNodeMap_JavaScriptObject_ListMixin, A.__SpeechRecognitionResultList_JavaScriptObject_ListMixin, A.__StyleSheetList_JavaScriptObject_ListMixin, A.Length, A._LengthList_JavaScriptObject_ListMixin, A.Number, A._NumberList_JavaScriptObject_ListMixin, A.PointList, A._StringList_JavaScriptObject_ListMixin, A.Transform, A._TransformList_JavaScriptObject_ListMixin, A.AudioBuffer, A._AudioParamMap_JavaScriptObject_MapMixin]);
+    _inheritMany(J.LegacyJavaScriptObject, [J.PlainJavaScriptObject, J.UnknownJavaScriptObject, J.JavaScriptFunction]);
     _inherit(J.JSUnmodifiableArray, J.JSArray);
     _inheritMany(J.JSNumber, [J.JSInt, J.JSNumNotInt]);
     _inheritMany(A.Stream, [A.CastStream, A._StreamImpl, A._EmptyStream]);
-    _inheritMany(A.Error, [A.LateError, A.TypeError, A.JsNoSuchMethodError, A.UnknownJsTypeError, A.RuntimeError, A.AssertionError, A._Error, A.JsonUnsupportedObjectError, A.NullThrownError, A.ArgumentError, A.NoSuchMethodError, A.UnsupportedError, A.UnimplementedError, A.StateError, A.ConcurrentModificationError, A.CyclicInitializationError]);
-    _inherit(A.ListBase, A._ListBase_Object_ListMixin);
+    _inheritMany(A.Iterable, [A._CastIterableBase, A.EfficientLengthIterable, A.MappedIterable, A.WhereIterable, A.ExpandIterable, A.TakeIterable, A.SkipIterable, A.SkipWhileIterable, A.WhereTypeIterable, A._KeysOrValues, A._AllMatchesIterable, A._StringAllMatchesIterable]);
+    _inheritMany(A._CastIterableBase, [A.CastIterable, A.__CastListBase__CastIterableBase_ListMixin]);
+    _inherit(A._EfficientLengthCastIterable, A.CastIterable);
+    _inherit(A._CastListBase, A.__CastListBase__CastIterableBase_ListMixin);
+    _inherit(A.CastList, A._CastListBase);
+    _inheritMany(A.Error, [A.LateError, A.TypeError, A.JsNoSuchMethodError, A.UnknownJsTypeError, A._CyclicInitializationError, A.RuntimeError, A.AssertionError, A._Error, A.JsonUnsupportedObjectError, A.ArgumentError, A.NoSuchMethodError, A.UnsupportedError, A.UnimplementedError, A.StateError, A.ConcurrentModificationError]);
     _inherit(A.UnmodifiableListBase, A.ListBase);
     _inherit(A.CodeUnits, A.UnmodifiableListBase);
-    _inheritMany(A.Closure, [A.Closure0Args, A.Instantiation, A.Closure2Args, A.TearOffClosure, A.JsLinkedHashMap_values_closure, A.initHooks_closure, A.initHooks_closure1, A._AsyncRun__initializeScheduleImmediate_internalCallback, A._AsyncRun__initializeScheduleImmediate_closure, A._awaitOnObject_closure, A._Future__chainForeignFuture_closure, A._Future__propagateToListeners_handleWhenCompleteCallback_closure, A.Stream_pipe_closure, A.Stream_length_closure, A._CustomZone_bindUnaryCallback_closure, A._CustomZone_bindUnaryCallbackGuarded_closure, A._RootZone_bindUnaryCallback_closure, A._RootZone_bindUnaryCallbackGuarded_closure, A.runZonedGuarded_closure, A._Uri__makePath_closure, A._createTables_setChars, A._createTables_setRange, A._convertDataTree__convert, A.promiseToFuture_closure, A.promiseToFuture_closure0, A.dartify_convert, A.Context_joinAll_closure, A.Context_split_closure, A._validateArgList_closure, A.WindowsStyle_absolutePathToUri_closure, A.Chain_Chain$parse_closure, A.Chain_Chain$parse_closure0, A.Chain_Chain$parse_closure1, A.Chain_toTrace_closure, A.Chain_toString_closure0, A.Chain_toString__closure0, A.Chain_toString_closure, A.Chain_toString__closure, A.Trace__parseVM_closure, A.Trace__parseVM_closure0, A.Trace$parseV8_closure, A.Trace$parseV8_closure0, A.Trace$parseJSCore_closure, A.Trace$parseJSCore_closure0, A.Trace$parseFirefox_closure, A.Trace$parseFirefox_closure0, A.Trace$parseFriendly_closure, A.Trace$parseFriendly_closure0, A.Trace_terse_closure, A.Trace_foldFrames_closure, A.Trace_foldFrames_closure0, A.Trace_toString_closure0, A.Trace_toString_closure, A._GuaranteeSink_addStream_closure, A._MultiChannel_closure, A._MultiChannel_closure1, A._MultiChannel_virtualChannel_closure, A.main__closure, A.main__closure0, A.main__closure1, A._connectToServer_closure, A._connectToServer_closure0, A._connectToIframe_closure, A._connectToIframe_closure0, A._connectToIframe_closure1]);
-    _inheritMany(A.Closure0Args, [A.nullFuture_closure, A._AsyncRun__scheduleImmediateJsOverride_internalCallback, A._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback, A._TimerImpl_internalCallback, A._TimerImpl$periodic_closure, A._Future__addListener_closure, A._Future__prependListeners_closure, A._Future__chainForeignFuture_closure1, A._Future__asyncCompleteWithValue_closure, A._Future__chainFuture_closure, A._Future__asyncCompleteError_closure, A._Future__propagateToListeners_handleWhenCompleteCallback, A._Future__propagateToListeners_handleValueCallback, A._Future__propagateToListeners_handleError, A.Stream_length_closure0, A._StreamController__subscribe_closure, A._StreamController__recordCancel_complete, A._AddStreamState_cancel_closure, A._BufferingStreamSubscription__sendError_sendError, A._BufferingStreamSubscription__sendDone_sendDone, A._PendingEvents_schedule_closure, A._CustomZone_bindCallback_closure, A._CustomZone_bindCallbackGuarded_closure, A._rootHandleError_closure, A._RootZone_bindCallback_closure, A._RootZone_bindCallbackGuarded_closure, A.Utf8Decoder__decoder_closure, A.Utf8Decoder__decoderNonfatal_closure, A.NullStreamSink_addStream_closure, A.Frame_Frame$parseVM_closure, A.Frame_Frame$parseV8_closure, A.Frame_Frame$_parseFirefoxEval_closure, A.Frame_Frame$parseFirefox_closure, A.Frame_Frame$parseFriendly_closure, A.LazyTrace_terse_closure, A.Trace_Trace$from_closure, A.GuaranteeChannel_closure, A.GuaranteeChannel__closure, A._MultiChannel_closure0, A._MultiChannel__closure, A._MultiChannel_virtualChannel_closure0, A.main_closure, A.main__closure2, A.main__closure3]);
-    _inheritMany(A.Iterable, [A.EfficientLengthIterable, A.MappedIterable, A.WhereIterable, A.ExpandIterable, A.TakeIterable, A.SkipWhileIterable, A.WhereTypeIterable, A._ConstantMapKeyIterable, A.IterableBase, A._StringAllMatchesIterable]);
-    _inheritMany(A.EfficientLengthIterable, [A.ListIterable, A.LinkedHashMapKeyIterable, A._HashMapKeyIterable]);
+    _inheritMany(A.Closure, [A.Closure0Args, A.Instantiation, A.Closure2Args, A.TearOffClosure, A.JsLinkedHashMap_values_closure, A.initHooks_closure, A.initHooks_closure1, A._AsyncRun__initializeScheduleImmediate_internalCallback, A._AsyncRun__initializeScheduleImmediate_closure, A._Future__chainForeignFuture_closure, A._Future__propagateToListeners_handleWhenCompleteCallback_closure, A.Stream_pipe_closure, A.Stream_length_closure, A._CustomZone_bindUnaryCallback_closure, A._CustomZone_bindUnaryCallbackGuarded_closure, A._RootZone_bindUnaryCallback_closure, A._RootZone_bindUnaryCallbackGuarded_closure, A.runZonedGuarded_closure, A._Uri__makePath_closure, A._createTables_setChars, A._createTables_setRange, A.jsify__convert, A.promiseToFuture_closure, A.promiseToFuture_closure0, A.dartify_convert, A.Context_joinAll_closure, A.Context_split_closure, A._validateArgList_closure, A.WindowsStyle_absolutePathToUri_closure, A.Chain_Chain$parse_closure, A.Chain_toTrace_closure, A.Chain_toString_closure0, A.Chain_toString__closure0, A.Chain_toString_closure, A.Chain_toString__closure, A.Trace__parseVM_closure, A.Trace$parseV8_closure, A.Trace$parseJSCore_closure, A.Trace$parseFirefox_closure, A.Trace$parseFriendly_closure, A.Trace_terse_closure, A.Trace_foldFrames_closure, A.Trace_foldFrames_closure0, A.Trace_toString_closure0, A.Trace_toString_closure, A._GuaranteeSink_addStream_closure, A._MultiChannel_closure, A._MultiChannel_closure1, A._MultiChannel_virtualChannel_closure, A.MessagePortExtension_get_postMessage_closure, A.main__closure, A.main__closure0, A.main__closure1, A._connectToServer_closure, A._connectToServer_closure0, A._connectToIframe_closure, A._connectToIframe__closure2, A._connectToIframe__closure3]);
+    _inheritMany(A.Closure0Args, [A.nullFuture_closure, A._AsyncRun__scheduleImmediateJsOverride_internalCallback, A._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback, A._TimerImpl_internalCallback, A._TimerImpl$periodic_closure, A._Future__addListener_closure, A._Future__prependListeners_closure, A._Future__chainForeignFuture_closure1, A._Future__chainCoreFutureAsync_closure, A._Future__asyncCompleteWithValue_closure, A._Future__asyncCompleteError_closure, A._Future__propagateToListeners_handleWhenCompleteCallback, A._Future__propagateToListeners_handleValueCallback, A._Future__propagateToListeners_handleError, A.Stream_length_closure0, A._StreamController__subscribe_closure, A._StreamController__recordCancel_complete, A._AddStreamState_cancel_closure, A._BufferingStreamSubscription__sendError_sendError, A._BufferingStreamSubscription__sendDone_sendDone, A._PendingEvents_schedule_closure, A._CustomZone_bindCallback_closure, A._CustomZone_bindCallbackGuarded_closure, A._rootHandleError_closure, A._RootZone_bindCallback_closure, A._RootZone_bindCallbackGuarded_closure, A.Utf8Decoder__decoder_closure, A.Utf8Decoder__decoderNonfatal_closure, A.NullStreamSink_addStream_closure, A.Frame_Frame$parseVM_closure, A.Frame_Frame$parseV8_closure, A.Frame_Frame$_parseFirefoxEval_closure, A.Frame_Frame$parseFirefox_closure, A.Frame_Frame$parseFriendly_closure, A.LazyTrace_terse_closure, A.Trace_Trace$from_closure, A.GuaranteeChannel_closure, A.GuaranteeChannel__closure, A._MultiChannel_closure0, A._MultiChannel__closure, A._MultiChannel_virtualChannel_closure0, A.main_closure, A.main__closure2, A.main__closure3, A._connectToIframe__closure, A._connectToIframe__closure0, A._connectToIframe__closure1]);
+    _inheritMany(A.EfficientLengthIterable, [A.ListIterable, A.EmptyIterable, A.LinkedHashMapKeyIterable, A._HashMapKeyIterable]);
     _inheritMany(A.ListIterable, [A.SubListIterable, A.MappedListIterable, A.ReversedListIterable, A._JsonMapKeyIterable]);
     _inherit(A.EfficientLengthMappedIterable, A.MappedIterable);
-    _inheritMany(A.Iterator, [A.MappedIterator, A.WhereIterator, A.TakeIterator, A.SkipWhileIterator]);
     _inherit(A.EfficientLengthTakeIterable, A.TakeIterable);
+    _inherit(A.EfficientLengthSkipIterable, A.SkipIterable);
     _inherit(A._UnmodifiableMapView_MapView__UnmodifiableMapMixin, A.MapView);
     _inherit(A.UnmodifiableMapView, A._UnmodifiableMapView_MapView__UnmodifiableMapMixin);
     _inherit(A.ConstantMapView, A.UnmodifiableMapView);
     _inherit(A.ConstantStringMap, A.ConstantMap);
     _inherit(A.Instantiation1, A.Instantiation);
-    _inheritMany(A.Closure2Args, [A.Primitives_functionNoSuchMethod_closure, A.initHooks_closure0, A._awaitOnObject_closure0, A._wrapJsFunctionForAsync_closure, A._Future__chainForeignFuture_closure0, A.MapBase_mapToString_closure, A._JsonStringifier_writeMap_closure, A.NoSuchMethodError_toString_closure, A.Uri_splitQueryString_closure, A.Uri__parseIPv4Address_error, A.Uri_parseIPv6Address_error, A.Uri_parseIPv6Address_parseHex, A._createTables_build, A.MidiInputMap_keys_closure, A.MidiOutputMap_keys_closure, A.RtcStatsReport_keys_closure, A.Storage_keys_closure, A.AudioParamMap_keys_closure, A.Frame_Frame$parseV8_closure_parseLocation, A.main_closure0]);
+    _inheritMany(A.Closure2Args, [A.Primitives_functionNoSuchMethod_closure, A.initHooks_closure0, A._Future__chainForeignFuture_closure0, A.MapBase_mapToString_closure, A._JsonStringifier_writeMap_closure, A.NoSuchMethodError_toString_closure, A.Uri_splitQueryString_closure, A.Uri__parseIPv4Address_error, A.Uri_parseIPv6Address_error, A.Uri_parseIPv6Address_parseHex, A._createTables_build, A.MidiInputMap_keys_closure, A.MidiOutputMap_keys_closure, A.RtcStatsReport_keys_closure, A.Storage_keys_closure, A.AudioParamMap_keys_closure, A.Frame_Frame$parseV8_closure_parseLocation, A.main_closure0]);
     _inherit(A.NullError, A.TypeError);
     _inheritMany(A.TearOffClosure, [A.StaticClosure, A.BoundClosure]);
     _inherit(A._AssertionError, A.AssertionError);
-    _inherit(A.MapBase, A.MapMixin);
     _inheritMany(A.MapBase, [A.JsLinkedHashMap, A._HashMap, A._JsonMap]);
-    _inherit(A._AllMatchesIterable, A.IterableBase);
-    _inherit(A.NativeTypedArray, A.NativeTypedData);
+    _inheritMany(A.NativeTypedData, [A.NativeByteData, A.NativeTypedArray]);
     _inheritMany(A.NativeTypedArray, [A._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin, A._NativeTypedArrayOfInt_NativeTypedArray_ListMixin]);
     _inherit(A._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin, A._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin);
     _inherit(A.NativeTypedArrayOfDouble, A._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin);
     _inherit(A._NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin, A._NativeTypedArrayOfInt_NativeTypedArray_ListMixin);
     _inherit(A.NativeTypedArrayOfInt, A._NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin);
+    _inheritMany(A.NativeTypedArrayOfDouble, [A.NativeFloat32List, A.NativeFloat64List]);
     _inheritMany(A.NativeTypedArrayOfInt, [A.NativeInt16List, A.NativeInt32List, A.NativeInt8List, A.NativeUint16List, A.NativeUint32List, A.NativeUint8ClampedList, A.NativeUint8List]);
     _inherit(A._TypeError, A._Error);
     _inheritMany(A._Completer, [A._AsyncCompleter, A._SyncCompleter]);
@@ -16540,11 +17541,10 @@
     _inheritMany(A._DelayedEvent, [A._DelayedData, A._DelayedError]);
     _inheritMany(A._Zone, [A._CustomZone, A._RootZone]);
     _inherit(A._IdentityHashMap, A._HashMap);
-    _inherit(A._SetBase, A.__SetBase_Object_SetMixin);
+    _inherit(A._SetBase, A.SetBase);
     _inherit(A._LinkedHashSet, A._SetBase);
     _inheritMany(A.Codec, [A.Encoding, A.Base64Codec, A._FusedCodec, A.JsonCodec]);
     _inheritMany(A.Encoding, [A.AsciiCodec, A.Utf8Codec]);
-    _inherit(A.Converter, A.StreamTransformerBase);
     _inheritMany(A.Converter, [A._UnicodeSubsetEncoder, A.Base64Encoder, A.JsonEncoder, A.JsonDecoder, A.Utf8Encoder, A.Utf8Decoder]);
     _inherit(A.AsciiEncoder, A._UnicodeSubsetEncoder);
     _inherit(A.JsonCyclicError, A.JsonUnsupportedObjectError);
@@ -16611,83 +17611,77 @@
     _inherit(A.InternalStyle, A.Style);
     _inheritMany(A.InternalStyle, [A.PosixStyle, A.UrlStyle, A.WindowsStyle]);
     _inheritMany(A.StreamChannelMixin, [A.GuaranteeChannel, A._MultiChannel, A.VirtualChannel]);
-    _inheritMany(A.EventTarget0, [A.Window0, A.Node0, A.MessagePort0, A.WebSocket0]);
-    _inheritMany(A.Node0, [A.Document0, A.Element0]);
-    _inherit(A.HTMLDocument, A.Document0);
-    _inherit(A.HTMLElement, A.Element0);
-    _inheritMany(A.HTMLElement, [A.HTMLBodyElement, A.HTMLScriptElement, A.HTMLIFrameElement]);
-    _inherit(A.MessageEvent0, A.Event0);
     _mixin(A.UnmodifiableListBase, A.UnmodifiableListMixin);
-    _mixin(A._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin, A.ListMixin);
+    _mixin(A.__CastListBase__CastIterableBase_ListMixin, A.ListBase);
+    _mixin(A._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin, A.ListBase);
     _mixin(A._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin, A.FixedLengthListMixin);
-    _mixin(A._NativeTypedArrayOfInt_NativeTypedArray_ListMixin, A.ListMixin);
+    _mixin(A._NativeTypedArrayOfInt_NativeTypedArray_ListMixin, A.ListBase);
     _mixin(A._NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin, A.FixedLengthListMixin);
     _mixin(A._SyncStreamController, A._SyncStreamControllerDispatch);
-    _mixin(A._ListBase_Object_ListMixin, A.ListMixin);
     _mixin(A._UnmodifiableMapView_MapView__UnmodifiableMapMixin, A._UnmodifiableMapMixin);
-    _mixin(A.__SetBase_Object_SetMixin, A.SetMixin);
     _mixin(A._CssStyleDeclaration_JavaScriptObject_CssStyleDeclarationBase, A.CssStyleDeclarationBase);
-    _mixin(A._DomRectList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._DomRectList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._DomRectList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._DomStringList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._DomStringList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._DomStringList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._FileList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._FileList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._FileList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._HtmlCollection_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._HtmlCollection_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._HtmlCollection_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._MidiInputMap_JavaScriptObject_MapMixin, A.MapMixin);
-    _mixin(A._MidiOutputMap_JavaScriptObject_MapMixin, A.MapMixin);
-    _mixin(A._MimeTypeArray_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._MidiInputMap_JavaScriptObject_MapMixin, A.MapBase);
+    _mixin(A._MidiOutputMap_JavaScriptObject_MapMixin, A.MapBase);
+    _mixin(A._MimeTypeArray_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._MimeTypeArray_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._NodeList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._NodeList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._NodeList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._PluginArray_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._PluginArray_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._PluginArray_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._RtcStatsReport_JavaScriptObject_MapMixin, A.MapMixin);
-    _mixin(A._SourceBufferList_EventTarget_ListMixin, A.ListMixin);
+    _mixin(A._RtcStatsReport_JavaScriptObject_MapMixin, A.MapBase);
+    _mixin(A._SourceBufferList_EventTarget_ListMixin, A.ListBase);
     _mixin(A._SourceBufferList_EventTarget_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._SpeechGrammarList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._SpeechGrammarList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._SpeechGrammarList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._Storage_JavaScriptObject_MapMixin, A.MapMixin);
-    _mixin(A._TextTrackCueList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._Storage_JavaScriptObject_MapMixin, A.MapBase);
+    _mixin(A._TextTrackCueList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._TextTrackCueList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._TextTrackList_EventTarget_ListMixin, A.ListMixin);
+    _mixin(A._TextTrackList_EventTarget_ListMixin, A.ListBase);
     _mixin(A._TextTrackList_EventTarget_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._TouchList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._TouchList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._TouchList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A.__CssRuleList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A.__CssRuleList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A.__CssRuleList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A.__GamepadList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A.__GamepadList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A.__GamepadList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A.__NamedNodeMap_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A.__NamedNodeMap_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A.__NamedNodeMap_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A.__SpeechRecognitionResultList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A.__SpeechRecognitionResultList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A.__SpeechRecognitionResultList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A.__StyleSheetList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A.__StyleSheetList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A.__StyleSheetList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._LengthList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._LengthList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._LengthList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._NumberList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._NumberList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._NumberList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._StringList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._StringList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._StringList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._TransformList_JavaScriptObject_ListMixin, A.ListMixin);
+    _mixin(A._TransformList_JavaScriptObject_ListMixin, A.ListBase);
     _mixin(A._TransformList_JavaScriptObject_ListMixin_ImmutableListMixin, A.ImmutableListMixin);
-    _mixin(A._AudioParamMap_JavaScriptObject_MapMixin, A.MapMixin);
+    _mixin(A._AudioParamMap_JavaScriptObject_MapMixin, A.MapBase);
   })();
   var init = {
     typeUniverse: {eC: new Map(), tR: {}, eT: {}, tPV: {}, sEA: []},
     mangledGlobalNames: {int: "int", double: "double", num: "num", String: "String", bool: "bool", Null: "Null", List: "List"},
     mangledNames: {},
-    types: ["~()", "bool(String)", "Null()", "~(@)", "Frame(String)", "~(String,@)", "Frame()", "~(JavaScriptObject)", "Null(@)", "~(~())", "~(Object,StackTrace)", "~(Object[StackTrace?])", "~(Object?)", "bool(Frame)", "@(@)", "Trace()", "String(Frame)", "int(Frame)", "Trace(String)", "@()", "Object?(Object?)", "~(Object?,Object?)", "~(Uint8List,String,int)", "String(String)", "~(String,int)", "~(String,int?)", "int(int,int)", "Map<String,String>(Map<String,String>,String)", "Uint8List(@,@)", "~(Symbol0,@)", "~(String,String)", "~(Zone,ZoneDelegate,Zone,Object,StackTrace)", "Future<@>(@)", "String(String?)", "_Future<@>(@)", "List<Frame>(Trace)", "int(Trace)", "Null(Object,StackTrace)", "String(Trace)", "~([Object?])", "~(int,@)", "Frame(String,String)", "@(@,String)", "0^(0^,0^)<num>", "Future<Null>()", "Frame(Frame)", "~(List<@>)", "~(Timer)", "Null(~())", "Future<~>(@)", "@(String)", "~(Zone?,ZoneDelegate?,Zone,Object,StackTrace)", "0^(Zone?,ZoneDelegate?,Zone,0^())<Object?>", "0^(Zone?,ZoneDelegate?,Zone,0^(1^),1^)<Object?Object?>", "0^(Zone?,ZoneDelegate?,Zone,0^(1^,2^),1^,2^)<Object?Object?Object?>", "0^()(Zone,ZoneDelegate,Zone,0^())<Object?>", "0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))<Object?Object?>", "0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))<Object?Object?Object?>", "AsyncError?(Zone,ZoneDelegate,Zone,Object,StackTrace?)", "~(Zone?,ZoneDelegate?,Zone,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~(Timer))", "~(Zone,ZoneDelegate,Zone,String)", "~(String)", "Zone(Zone?,ZoneDelegate?,Zone,ZoneSpecification?,Map<Object?,Object?>?)", "Null(@,StackTrace)"],
+    types: ["~()", "bool(String)", "Null()", "~(String,@)", "@()", "~(@)", "Frame()", "~(JavaScriptObject)", "~(Object?)", "Frame(String)", "Null(@)", "~(Object,StackTrace)", "~(Object[StackTrace?])", "~(~())", "Trace(String)", "@(@)", "~(Object?,Object?)", "String(String)", "~(Uint8List,String,int)", "Object?(Object?)", "int(Frame)", "String(Frame)", "Trace()", "bool(Frame)", "~(String,int)", "Uint8List(@,@)", "Null(Object,StackTrace)", "~(String,String)", "_Future<@>(@)", "Future<@>(@)", "Null(~())", "String(String?)", "List<Frame>(Trace)", "int(Trace)", "~(Zone,ZoneDelegate,Zone,Object,StackTrace)", "String(Trace)", "@(@,String)", "@(String)", "Frame(String,String)", "~(Symbol0,@)", "Map<String,String>(Map<String,String>,String)", "0^(0^,0^)<num>", "~(List<@>)", "~(Timer)", "~([Object?])", "~(String,int?)", "~(Zone?,ZoneDelegate?,Zone,Object,StackTrace)", "0^(Zone?,ZoneDelegate?,Zone,0^())<Object?>", "0^(Zone?,ZoneDelegate?,Zone,0^(1^),1^)<Object?,Object?>", "0^(Zone?,ZoneDelegate?,Zone,0^(1^,2^),1^,2^)<Object?,Object?,Object?>", "0^()(Zone,ZoneDelegate,Zone,0^())<Object?>", "0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))<Object?,Object?>", "0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))<Object?,Object?,Object?>", "AsyncError?(Zone,ZoneDelegate,Zone,Object,StackTrace?)", "~(Zone?,ZoneDelegate?,Zone,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~())", "Timer(Zone,ZoneDelegate,Zone,Duration,~(Timer))", "~(Zone,ZoneDelegate,Zone,String)", "~(String)", "Zone(Zone?,ZoneDelegate?,Zone,ZoneSpecification?,Map<Object?,Object?>?)", "int(int,int)", "Future<Null>()", "Frame(Frame)"],
     interceptorsByTag: null,
     leafTags: null,
     arrayRti: Symbol("$ti")
   };
-  A._Universe_addRules(init.typeUniverse, JSON.parse('{"PlainJavaScriptObject":"LegacyJavaScriptObject","UnknownJavaScriptObject":"LegacyJavaScriptObject","JavaScriptFunction":"LegacyJavaScriptObject","Window0":"LegacyJavaScriptObject","Document0":"LegacyJavaScriptObject","HTMLDocument":"LegacyJavaScriptObject","Navigator0":"LegacyJavaScriptObject","Element0":"LegacyJavaScriptObject","HTMLElement":"LegacyJavaScriptObject","HTMLBodyElement":"LegacyJavaScriptObject","Node0":"LegacyJavaScriptObject","EventTarget0":"LegacyJavaScriptObject","Event0":"LegacyJavaScriptObject","MessageEvent0":"LegacyJavaScriptObject","Location0":"LegacyJavaScriptObject","MessagePort0":"LegacyJavaScriptObject","CSSStyleDeclaration":"LegacyJavaScriptObject","HTMLScriptElement":"LegacyJavaScriptObject","DomTokenList0":"LegacyJavaScriptObject","HTMLIFrameElement":"LegacyJavaScriptObject","WebSocket0":"LegacyJavaScriptObject","MessageChannel0":"LegacyJavaScriptObject","TestRunner":"LegacyJavaScriptObject","_JSApi":"LegacyJavaScriptObject","AbortPaymentEvent":"JavaScriptObject","ExtendableEvent":"JavaScriptObject","Event":"JavaScriptObject","AudioContext":"BaseAudioContext","AbsoluteOrientationSensor":"EventTarget","OrientationSensor":"EventTarget","Sensor":"EventTarget","MathMLElement":"Element","AudioElement":"HtmlElement","MediaElement":"HtmlElement","HtmlDocument":"Node","Document":"Node","VttCue":"TextTrackCue","CDataSection":"CharacterData","Text":"CharacterData","HtmlFormControlsCollection":"HtmlCollection","CssCharsetRule":"CssRule","CssMatrixComponent":"CssTransformComponent","CssStyleSheet":"StyleSheet","CssurlImageValue":"CssStyleValue","CssImageValue":"CssStyleValue","CssResourceValue":"CssStyleValue","NativeFloat32List":"NativeTypedArrayOfDouble","JSBool":{"bool":[]},"JSNull":{"Null":[]},"LegacyJavaScriptObject":{"JavaScriptObject":[]},"JSArray":{"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"JSUnmodifiableArray":{"JSArray":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"ArrayIterator":{"Iterator":["1"]},"JSNumber":{"double":[],"num":[]},"JSInt":{"double":[],"int":[],"num":[]},"JSNumNotInt":{"double":[],"num":[]},"JSString":{"String":[],"Pattern":[]},"CastStream":{"Stream":["2"],"Stream.T":"2"},"CastStreamSubscription":{"StreamSubscription":["2"]},"LateError":{"Error":[]},"CodeUnits":{"ListMixin":["int"],"UnmodifiableListMixin":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"ListMixin.E":"int","UnmodifiableListMixin.E":"int"},"EfficientLengthIterable":{"Iterable":["1"]},"ListIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"SubListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"ListIterator":{"Iterator":["1"]},"MappedIterable":{"Iterable":["2"],"Iterable.E":"2"},"EfficientLengthMappedIterable":{"MappedIterable":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"Iterable.E":"2"},"MappedIterator":{"Iterator":["2"]},"MappedListIterable":{"ListIterable":["2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListIterable.E":"2","Iterable.E":"2"},"WhereIterable":{"Iterable":["1"],"Iterable.E":"1"},"WhereIterator":{"Iterator":["1"]},"ExpandIterable":{"Iterable":["2"],"Iterable.E":"2"},"ExpandIterator":{"Iterator":["2"]},"TakeIterable":{"Iterable":["1"],"Iterable.E":"1"},"EfficientLengthTakeIterable":{"TakeIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"TakeIterator":{"Iterator":["1"]},"SkipWhileIterable":{"Iterable":["1"],"Iterable.E":"1"},"SkipWhileIterator":{"Iterator":["1"]},"EmptyIterator":{"Iterator":["1"]},"WhereTypeIterable":{"Iterable":["1"],"Iterable.E":"1"},"WhereTypeIterator":{"Iterator":["1"]},"UnmodifiableListBase":{"ListMixin":["1"],"UnmodifiableListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"ReversedListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"Symbol":{"Symbol0":[]},"ConstantMapView":{"UnmodifiableMapView":["1","2"],"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"ConstantMap":{"Map":["1","2"]},"ConstantStringMap":{"ConstantMap":["1","2"],"Map":["1","2"]},"_ConstantMapKeyIterable":{"Iterable":["1"],"Iterable.E":"1"},"Instantiation":{"Closure":[],"Function":[]},"Instantiation1":{"Closure":[],"Function":[]},"JSInvocationMirror":{"Invocation":[]},"NullError":{"TypeError":[],"Error":[]},"JsNoSuchMethodError":{"Error":[]},"UnknownJsTypeError":{"Error":[]},"NullThrownFromJavaScriptException":{"Exception":[]},"_StackTrace":{"StackTrace":[]},"Closure":{"Function":[]},"Closure0Args":{"Closure":[],"Function":[]},"Closure2Args":{"Closure":[],"Function":[]},"TearOffClosure":{"Closure":[],"Function":[]},"StaticClosure":{"Closure":[],"Function":[]},"BoundClosure":{"Closure":[],"Function":[]},"RuntimeError":{"Error":[]},"_AssertionError":{"Error":[]},"JsLinkedHashMap":{"MapMixin":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapMixin.K":"1","MapMixin.V":"2"},"LinkedHashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"LinkedHashMapKeyIterator":{"Iterator":["1"]},"JSSyntaxRegExp":{"Pattern":[]},"_MatchImplementation":{"RegExpMatch":[],"Match":[]},"_AllMatchesIterable":{"Iterable":["RegExpMatch"],"Iterable.E":"RegExpMatch"},"_AllMatchesIterator":{"Iterator":["RegExpMatch"]},"StringMatch":{"Match":[]},"_StringAllMatchesIterable":{"Iterable":["Match"],"Iterable.E":"Match"},"_StringAllMatchesIterator":{"Iterator":["Match"]},"NativeTypedArray":{"JavaScriptIndexingBehavior":["1"]},"NativeTypedArrayOfDouble":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["double"],"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"ListMixin.E":"double"},"NativeTypedArrayOfInt":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"]},"NativeInt16List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeInt32List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeInt8List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint16List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint32List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint8ClampedList":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint8List":{"ListMixin":["int"],"Uint8List":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"_Error":{"Error":[]},"_TypeError":{"TypeError":[],"Error":[]},"AsyncError":{"Error":[]},"_Future":{"Future":["1"]},"_TimerImpl":{"Timer":[]},"_AsyncAwaitCompleter":{"Completer":["1"]},"_Completer":{"Completer":["1"]},"_AsyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_SyncCompleter":{"_Completer":["1"],"Completer":["1"]},"StreamTransformerBase":{"StreamTransformer":["1","2"]},"_StreamController":{"StreamController":["1"],"StreamSink":["1"],"StreamConsumer":["1"],"_StreamControllerLifecycle":["1"],"_EventDispatch":["1"]},"_SyncStreamController":{"_SyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"StreamConsumer":["1"],"_StreamControllerLifecycle":["1"],"_EventDispatch":["1"]},"_ControllerStream":{"_StreamImpl":["1"],"Stream":["1"],"Stream.T":"1"},"_ControllerSubscription":{"_BufferingStreamSubscription":["1"],"StreamSubscription":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamSinkWrapper":{"StreamSink":["1"],"StreamConsumer":["1"]},"_BufferingStreamSubscription":{"StreamSubscription":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamImpl":{"Stream":["1"]},"_DelayedData":{"_DelayedEvent":["1"]},"_DelayedError":{"_DelayedEvent":["@"]},"_DelayedDone":{"_DelayedEvent":["@"]},"_DoneStreamSubscription":{"StreamSubscription":["1"]},"_EmptyStream":{"Stream":["1"],"Stream.T":"1"},"_ZoneSpecification":{"ZoneSpecification":[]},"_ZoneDelegate":{"ZoneDelegate":[]},"_Zone":{"Zone":[]},"_CustomZone":{"_Zone":[],"Zone":[]},"_RootZone":{"_Zone":[],"Zone":[]},"_HashMap":{"MapMixin":["1","2"],"Map":["1","2"],"MapMixin.K":"1","MapMixin.V":"2"},"_IdentityHashMap":{"_HashMap":["1","2"],"MapMixin":["1","2"],"Map":["1","2"],"MapMixin.K":"1","MapMixin.V":"2"},"_HashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"_HashMapKeyIterator":{"Iterator":["1"]},"_LinkedHashSet":{"SetMixin":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_LinkedHashSetIterator":{"Iterator":["1"]},"IterableBase":{"Iterable":["1"]},"ListBase":{"ListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"MapBase":{"MapMixin":["1","2"],"Map":["1","2"]},"MapMixin":{"Map":["1","2"]},"MapView":{"Map":["1","2"]},"UnmodifiableMapView":{"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"_SetBase":{"SetMixin":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_JsonMap":{"MapMixin":["String","@"],"Map":["String","@"],"MapMixin.K":"String","MapMixin.V":"@"},"_JsonMapKeyIterable":{"ListIterable":["String"],"EfficientLengthIterable":["String"],"Iterable":["String"],"ListIterable.E":"String","Iterable.E":"String"},"AsciiCodec":{"Codec":["String","List<int>"],"Codec.S":"String"},"_UnicodeSubsetEncoder":{"Converter":["String","List<int>"],"StreamTransformer":["String","List<int>"]},"AsciiEncoder":{"Converter":["String","List<int>"],"StreamTransformer":["String","List<int>"]},"Base64Codec":{"Codec":["List<int>","String"],"Codec.S":"List<int>"},"Base64Encoder":{"Converter":["List<int>","String"],"StreamTransformer":["List<int>","String"]},"_FusedCodec":{"Codec":["1","3"],"Codec.S":"1"},"Converter":{"StreamTransformer":["1","2"]},"Encoding":{"Codec":["String","List<int>"]},"JsonUnsupportedObjectError":{"Error":[]},"JsonCyclicError":{"Error":[]},"JsonCodec":{"Codec":["Object?","String"],"Codec.S":"Object?"},"JsonEncoder":{"Converter":["Object?","String"],"StreamTransformer":["Object?","String"]},"JsonDecoder":{"Converter":["String","Object?"],"StreamTransformer":["String","Object?"]},"Utf8Codec":{"Codec":["String","List<int>"],"Codec.S":"String"},"Utf8Encoder":{"Converter":["String","List<int>"],"StreamTransformer":["String","List<int>"]},"Utf8Decoder":{"Converter":["List<int>","String"],"StreamTransformer":["List<int>","String"]},"double":{"num":[]},"int":{"num":[]},"List":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"RegExpMatch":{"Match":[]},"String":{"Pattern":[]},"AssertionError":{"Error":[]},"TypeError":{"Error":[]},"NullThrownError":{"Error":[]},"ArgumentError":{"Error":[]},"RangeError":{"Error":[]},"IndexError":{"Error":[]},"NoSuchMethodError":{"Error":[]},"UnsupportedError":{"Error":[]},"UnimplementedError":{"Error":[]},"StateError":{"Error":[]},"ConcurrentModificationError":{"Error":[]},"OutOfMemoryError":{"Error":[]},"StackOverflowError":{"Error":[]},"CyclicInitializationError":{"Error":[]},"_Exception":{"Exception":[]},"FormatException":{"Exception":[]},"_StringStackTrace":{"StackTrace":[]},"StringBuffer":{"StringSink":[]},"_Uri":{"Uri":[]},"_SimpleUri":{"Uri":[]},"_DataUri":{"Uri":[]},"CssRule":{"JavaScriptObject":[]},"File":{"JavaScriptObject":[]},"Gamepad":{"JavaScriptObject":[]},"MimeType":{"JavaScriptObject":[]},"Node":{"JavaScriptObject":[]},"Plugin":{"JavaScriptObject":[]},"SourceBuffer":{"JavaScriptObject":[]},"SpeechGrammar":{"JavaScriptObject":[]},"SpeechRecognitionResult":{"JavaScriptObject":[]},"StyleSheet":{"JavaScriptObject":[]},"TextTrack":{"JavaScriptObject":[]},"TextTrackCue":{"JavaScriptObject":[]},"Touch":{"JavaScriptObject":[]},"HtmlElement":{"Node":[],"JavaScriptObject":[]},"AccessibleNodeList":{"JavaScriptObject":[]},"AnchorElement":{"Node":[],"JavaScriptObject":[]},"AreaElement":{"Node":[],"JavaScriptObject":[]},"Blob":{"JavaScriptObject":[]},"CharacterData":{"Node":[],"JavaScriptObject":[]},"CssPerspective":{"JavaScriptObject":[]},"CssStyleDeclaration":{"JavaScriptObject":[]},"CssStyleValue":{"JavaScriptObject":[]},"CssTransformComponent":{"JavaScriptObject":[]},"CssTransformValue":{"JavaScriptObject":[]},"CssUnparsedValue":{"JavaScriptObject":[]},"DataTransferItemList":{"JavaScriptObject":[]},"DomException":{"JavaScriptObject":[]},"DomRectList":{"ListMixin":["Rectangle<num>"],"ImmutableListMixin":["Rectangle<num>"],"List":["Rectangle<num>"],"JavaScriptIndexingBehavior":["Rectangle<num>"],"JavaScriptObject":[],"EfficientLengthIterable":["Rectangle<num>"],"Iterable":["Rectangle<num>"],"ImmutableListMixin.E":"Rectangle<num>","ListMixin.E":"Rectangle<num>"},"DomRectReadOnly":{"JavaScriptObject":[],"Rectangle":["num"]},"DomStringList":{"ListMixin":["String"],"ImmutableListMixin":["String"],"List":["String"],"JavaScriptIndexingBehavior":["String"],"JavaScriptObject":[],"EfficientLengthIterable":["String"],"Iterable":["String"],"ImmutableListMixin.E":"String","ListMixin.E":"String"},"DomTokenList":{"JavaScriptObject":[]},"Element":{"Node":[],"JavaScriptObject":[]},"EventTarget":{"JavaScriptObject":[]},"FileList":{"ListMixin":["File"],"ImmutableListMixin":["File"],"List":["File"],"JavaScriptIndexingBehavior":["File"],"JavaScriptObject":[],"EfficientLengthIterable":["File"],"Iterable":["File"],"ImmutableListMixin.E":"File","ListMixin.E":"File"},"FileWriter":{"JavaScriptObject":[]},"FormElement":{"Node":[],"JavaScriptObject":[]},"History":{"JavaScriptObject":[]},"HtmlCollection":{"ListMixin":["Node"],"ImmutableListMixin":["Node"],"List":["Node"],"JavaScriptIndexingBehavior":["Node"],"JavaScriptObject":[],"EfficientLengthIterable":["Node"],"Iterable":["Node"],"ImmutableListMixin.E":"Node","ListMixin.E":"Node"},"Location":{"JavaScriptObject":[]},"MediaList":{"JavaScriptObject":[]},"MidiInputMap":{"JavaScriptObject":[],"MapMixin":["String","@"],"Map":["String","@"],"MapMixin.K":"String","MapMixin.V":"@"},"MidiOutputMap":{"JavaScriptObject":[],"MapMixin":["String","@"],"Map":["String","@"],"MapMixin.K":"String","MapMixin.V":"@"},"MimeTypeArray":{"ListMixin":["MimeType"],"ImmutableListMixin":["MimeType"],"List":["MimeType"],"JavaScriptIndexingBehavior":["MimeType"],"JavaScriptObject":[],"EfficientLengthIterable":["MimeType"],"Iterable":["MimeType"],"ImmutableListMixin.E":"MimeType","ListMixin.E":"MimeType"},"NodeList":{"ListMixin":["Node"],"ImmutableListMixin":["Node"],"List":["Node"],"JavaScriptIndexingBehavior":["Node"],"JavaScriptObject":[],"EfficientLengthIterable":["Node"],"Iterable":["Node"],"ImmutableListMixin.E":"Node","ListMixin.E":"Node"},"PluginArray":{"ListMixin":["Plugin"],"ImmutableListMixin":["Plugin"],"List":["Plugin"],"JavaScriptIndexingBehavior":["Plugin"],"JavaScriptObject":[],"EfficientLengthIterable":["Plugin"],"Iterable":["Plugin"],"ImmutableListMixin.E":"Plugin","ListMixin.E":"Plugin"},"RtcStatsReport":{"JavaScriptObject":[],"MapMixin":["String","@"],"Map":["String","@"],"MapMixin.K":"String","MapMixin.V":"@"},"SelectElement":{"Node":[],"JavaScriptObject":[]},"SourceBufferList":{"ListMixin":["SourceBuffer"],"ImmutableListMixin":["SourceBuffer"],"List":["SourceBuffer"],"JavaScriptIndexingBehavior":["SourceBuffer"],"JavaScriptObject":[],"EfficientLengthIterable":["SourceBuffer"],"Iterable":["SourceBuffer"],"ImmutableListMixin.E":"SourceBuffer","ListMixin.E":"SourceBuffer"},"SpeechGrammarList":{"ListMixin":["SpeechGrammar"],"ImmutableListMixin":["SpeechGrammar"],"List":["SpeechGrammar"],"JavaScriptIndexingBehavior":["SpeechGrammar"],"JavaScriptObject":[],"EfficientLengthIterable":["SpeechGrammar"],"Iterable":["SpeechGrammar"],"ImmutableListMixin.E":"SpeechGrammar","ListMixin.E":"SpeechGrammar"},"Storage":{"JavaScriptObject":[],"MapMixin":["String","String"],"Map":["String","String"],"MapMixin.K":"String","MapMixin.V":"String"},"TextTrackCueList":{"ListMixin":["TextTrackCue"],"ImmutableListMixin":["TextTrackCue"],"List":["TextTrackCue"],"JavaScriptIndexingBehavior":["TextTrackCue"],"JavaScriptObject":[],"EfficientLengthIterable":["TextTrackCue"],"Iterable":["TextTrackCue"],"ImmutableListMixin.E":"TextTrackCue","ListMixin.E":"TextTrackCue"},"TextTrackList":{"ListMixin":["TextTrack"],"ImmutableListMixin":["TextTrack"],"List":["TextTrack"],"JavaScriptIndexingBehavior":["TextTrack"],"JavaScriptObject":[],"EfficientLengthIterable":["TextTrack"],"Iterable":["TextTrack"],"ImmutableListMixin.E":"TextTrack","ListMixin.E":"TextTrack"},"TimeRanges":{"JavaScriptObject":[]},"TouchList":{"ListMixin":["Touch"],"ImmutableListMixin":["Touch"],"List":["Touch"],"JavaScriptIndexingBehavior":["Touch"],"JavaScriptObject":[],"EfficientLengthIterable":["Touch"],"Iterable":["Touch"],"ImmutableListMixin.E":"Touch","ListMixin.E":"Touch"},"TrackDefaultList":{"JavaScriptObject":[]},"Url":{"JavaScriptObject":[]},"VideoTrackList":{"JavaScriptObject":[]},"_CssRuleList":{"ListMixin":["CssRule"],"ImmutableListMixin":["CssRule"],"List":["CssRule"],"JavaScriptIndexingBehavior":["CssRule"],"JavaScriptObject":[],"EfficientLengthIterable":["CssRule"],"Iterable":["CssRule"],"ImmutableListMixin.E":"CssRule","ListMixin.E":"CssRule"},"_DomRect":{"JavaScriptObject":[],"Rectangle":["num"]},"_GamepadList":{"ListMixin":["Gamepad?"],"ImmutableListMixin":["Gamepad?"],"List":["Gamepad?"],"JavaScriptIndexingBehavior":["Gamepad?"],"JavaScriptObject":[],"EfficientLengthIterable":["Gamepad?"],"Iterable":["Gamepad?"],"ImmutableListMixin.E":"Gamepad?","ListMixin.E":"Gamepad?"},"_NamedNodeMap":{"ListMixin":["Node"],"ImmutableListMixin":["Node"],"List":["Node"],"JavaScriptIndexingBehavior":["Node"],"JavaScriptObject":[],"EfficientLengthIterable":["Node"],"Iterable":["Node"],"ImmutableListMixin.E":"Node","ListMixin.E":"Node"},"_SpeechRecognitionResultList":{"ListMixin":["SpeechRecognitionResult"],"ImmutableListMixin":["SpeechRecognitionResult"],"List":["SpeechRecognitionResult"],"JavaScriptIndexingBehavior":["SpeechRecognitionResult"],"JavaScriptObject":[],"EfficientLengthIterable":["SpeechRecognitionResult"],"Iterable":["SpeechRecognitionResult"],"ImmutableListMixin.E":"SpeechRecognitionResult","ListMixin.E":"SpeechRecognitionResult"},"_StyleSheetList":{"ListMixin":["StyleSheet"],"ImmutableListMixin":["StyleSheet"],"List":["StyleSheet"],"JavaScriptIndexingBehavior":["StyleSheet"],"JavaScriptObject":[],"EfficientLengthIterable":["StyleSheet"],"Iterable":["StyleSheet"],"ImmutableListMixin.E":"StyleSheet","ListMixin.E":"StyleSheet"},"FixedSizeListIterator":{"Iterator":["1"]},"NullRejectionException":{"Exception":[]},"Length":{"JavaScriptObject":[]},"Number":{"JavaScriptObject":[]},"Transform":{"JavaScriptObject":[]},"LengthList":{"ListMixin":["Length"],"ImmutableListMixin":["Length"],"List":["Length"],"JavaScriptObject":[],"EfficientLengthIterable":["Length"],"Iterable":["Length"],"ImmutableListMixin.E":"Length","ListMixin.E":"Length"},"NumberList":{"ListMixin":["Number"],"ImmutableListMixin":["Number"],"List":["Number"],"JavaScriptObject":[],"EfficientLengthIterable":["Number"],"Iterable":["Number"],"ImmutableListMixin.E":"Number","ListMixin.E":"Number"},"PointList":{"JavaScriptObject":[]},"StringList":{"ListMixin":["String"],"ImmutableListMixin":["String"],"List":["String"],"JavaScriptObject":[],"EfficientLengthIterable":["String"],"Iterable":["String"],"ImmutableListMixin.E":"String","ListMixin.E":"String"},"TransformList":{"ListMixin":["Transform"],"ImmutableListMixin":["Transform"],"List":["Transform"],"JavaScriptObject":[],"EfficientLengthIterable":["Transform"],"Iterable":["Transform"],"ImmutableListMixin.E":"Transform","ListMixin.E":"Transform"},"AudioBuffer":{"JavaScriptObject":[]},"AudioParamMap":{"JavaScriptObject":[],"MapMixin":["String","@"],"Map":["String","@"],"MapMixin.K":"String","MapMixin.V":"@"},"AudioTrackList":{"JavaScriptObject":[]},"BaseAudioContext":{"JavaScriptObject":[]},"OfflineAudioContext":{"JavaScriptObject":[]},"NullStreamSink":{"StreamSink":["1"],"StreamConsumer":["1"]},"PathException":{"Exception":[]},"PosixStyle":{"InternalStyle":[]},"UrlStyle":{"InternalStyle":[]},"WindowsStyle":{"InternalStyle":[]},"Chain":{"StackTrace":[]},"LazyTrace":{"Trace":[],"StackTrace":[]},"Trace":{"StackTrace":[]},"UnparsedFrame":{"Frame":[]},"GuaranteeChannel":{"StreamChannelMixin":["1"],"StreamChannel":["1"]},"_GuaranteeSink":{"StreamSink":["1"],"StreamConsumer":["1"]},"_MultiChannel":{"StreamChannelMixin":["1"],"MultiChannel":["1"],"StreamChannel":["1"]},"VirtualChannel":{"StreamChannelMixin":["1"],"MultiChannel":["1"],"StreamChannel":["1"]},"StreamChannelMixin":{"StreamChannel":["1"]},"Uint8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]}}'));
-  A._Universe_addErasedTypes(init.typeUniverse, JSON.parse('{"EfficientLengthIterable":1,"UnmodifiableListBase":1,"NativeTypedArray":1,"StreamTransformerBase":2,"IterableBase":1,"ListBase":1,"MapBase":2,"_SetBase":1,"_ListBase_Object_ListMixin":1,"__SetBase_Object_SetMixin":1}'));
+  A._Universe_addRules(init.typeUniverse, JSON.parse('{"PlainJavaScriptObject":"LegacyJavaScriptObject","UnknownJavaScriptObject":"LegacyJavaScriptObject","JavaScriptFunction":"LegacyJavaScriptObject","AbortPaymentEvent":"JavaScriptObject","ExtendableEvent":"JavaScriptObject","Event":"JavaScriptObject","AudioContext":"BaseAudioContext","AbsoluteOrientationSensor":"EventTarget","OrientationSensor":"EventTarget","Sensor":"EventTarget","MathMLElement":"Element","AudioElement":"HtmlElement","MediaElement":"HtmlElement","HtmlDocument":"Node","Document":"Node","VttCue":"TextTrackCue","CDataSection":"CharacterData","Text":"CharacterData","HtmlFormControlsCollection":"HtmlCollection","CssCharsetRule":"CssRule","CssMatrixComponent":"CssTransformComponent","CssStyleSheet":"StyleSheet","CssurlImageValue":"CssStyleValue","CssImageValue":"CssStyleValue","CssResourceValue":"CssStyleValue","JSBool":{"bool":[],"TrustedGetRuntimeType":[]},"JSNull":{"Null":[],"TrustedGetRuntimeType":[]},"LegacyJavaScriptObject":{"JavaScriptObject":[]},"JSArray":{"List":["1"],"JavaScriptObject":[],"EfficientLengthIterable":["1"],"Iterable":["1"]},"JSUnmodifiableArray":{"JSArray":["1"],"List":["1"],"JavaScriptObject":[],"EfficientLengthIterable":["1"],"Iterable":["1"]},"ArrayIterator":{"Iterator":["1"]},"JSNumber":{"double":[],"num":[]},"JSInt":{"double":[],"int":[],"num":[],"TrustedGetRuntimeType":[]},"JSNumNotInt":{"double":[],"num":[],"TrustedGetRuntimeType":[]},"JSString":{"String":[],"Pattern":[],"TrustedGetRuntimeType":[]},"CastStream":{"Stream":["2"],"Stream.T":"2"},"CastStreamSubscription":{"StreamSubscription":["2"]},"_CastIterableBase":{"Iterable":["2"]},"CastIterator":{"Iterator":["2"]},"CastIterable":{"_CastIterableBase":["1","2"],"Iterable":["2"],"Iterable.E":"2"},"_EfficientLengthCastIterable":{"CastIterable":["1","2"],"_CastIterableBase":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"Iterable.E":"2"},"_CastListBase":{"ListBase":["2"],"List":["2"],"_CastIterableBase":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"]},"CastList":{"_CastListBase":["1","2"],"ListBase":["2"],"List":["2"],"_CastIterableBase":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListBase.E":"2","Iterable.E":"2"},"LateError":{"Error":[]},"CodeUnits":{"ListBase":["int"],"UnmodifiableListMixin":["int"],"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"],"ListBase.E":"int","UnmodifiableListMixin.E":"int"},"EfficientLengthIterable":{"Iterable":["1"]},"ListIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"SubListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"ListIterator":{"Iterator":["1"]},"MappedIterable":{"Iterable":["2"],"Iterable.E":"2"},"EfficientLengthMappedIterable":{"MappedIterable":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"Iterable.E":"2"},"MappedIterator":{"Iterator":["2"]},"MappedListIterable":{"ListIterable":["2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListIterable.E":"2","Iterable.E":"2"},"WhereIterable":{"Iterable":["1"],"Iterable.E":"1"},"WhereIterator":{"Iterator":["1"]},"ExpandIterable":{"Iterable":["2"],"Iterable.E":"2"},"ExpandIterator":{"Iterator":["2"]},"TakeIterable":{"Iterable":["1"],"Iterable.E":"1"},"EfficientLengthTakeIterable":{"TakeIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"TakeIterator":{"Iterator":["1"]},"SkipIterable":{"Iterable":["1"],"Iterable.E":"1"},"EfficientLengthSkipIterable":{"SkipIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"SkipIterator":{"Iterator":["1"]},"SkipWhileIterable":{"Iterable":["1"],"Iterable.E":"1"},"SkipWhileIterator":{"Iterator":["1"]},"EmptyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"EmptyIterator":{"Iterator":["1"]},"WhereTypeIterable":{"Iterable":["1"],"Iterable.E":"1"},"WhereTypeIterator":{"Iterator":["1"]},"UnmodifiableListBase":{"ListBase":["1"],"UnmodifiableListMixin":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"ReversedListIterable":{"ListIterable":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"Symbol":{"Symbol0":[]},"ConstantMapView":{"UnmodifiableMapView":["1","2"],"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"ConstantMap":{"Map":["1","2"]},"ConstantStringMap":{"ConstantMap":["1","2"],"Map":["1","2"]},"_KeysOrValues":{"Iterable":["1"],"Iterable.E":"1"},"_KeysOrValuesOrElementsIterator":{"Iterator":["1"]},"Instantiation":{"Closure":[],"Function":[]},"Instantiation1":{"Closure":[],"Function":[]},"JSInvocationMirror":{"Invocation":[]},"NullError":{"TypeError":[],"Error":[]},"JsNoSuchMethodError":{"Error":[]},"UnknownJsTypeError":{"Error":[]},"NullThrownFromJavaScriptException":{"Exception":[]},"_StackTrace":{"StackTrace":[]},"Closure":{"Function":[]},"Closure0Args":{"Closure":[],"Function":[]},"Closure2Args":{"Closure":[],"Function":[]},"TearOffClosure":{"Closure":[],"Function":[]},"StaticClosure":{"Closure":[],"Function":[]},"BoundClosure":{"Closure":[],"Function":[]},"_CyclicInitializationError":{"Error":[]},"RuntimeError":{"Error":[]},"_AssertionError":{"Error":[]},"JsLinkedHashMap":{"MapBase":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"LinkedHashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"LinkedHashMapKeyIterator":{"Iterator":["1"]},"JSSyntaxRegExp":{"RegExp":[],"Pattern":[]},"_MatchImplementation":{"RegExpMatch":[],"Match":[]},"_AllMatchesIterable":{"Iterable":["RegExpMatch"],"Iterable.E":"RegExpMatch"},"_AllMatchesIterator":{"Iterator":["RegExpMatch"]},"StringMatch":{"Match":[]},"_StringAllMatchesIterable":{"Iterable":["Match"],"Iterable.E":"Match"},"_StringAllMatchesIterator":{"Iterator":["Match"]},"NativeByteBuffer":{"JavaScriptObject":[],"ByteBuffer":[],"TrustedGetRuntimeType":[]},"NativeTypedData":{"JavaScriptObject":[]},"NativeByteData":{"JavaScriptObject":[],"ByteData":[],"TrustedGetRuntimeType":[]},"NativeTypedArray":{"JavaScriptIndexingBehavior":["1"],"JavaScriptObject":[]},"NativeTypedArrayOfDouble":{"ListBase":["double"],"JavaScriptIndexingBehavior":["double"],"List":["double"],"JavaScriptObject":[],"EfficientLengthIterable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"]},"NativeTypedArrayOfInt":{"ListBase":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"]},"NativeFloat32List":{"ListBase":["double"],"Float32List":[],"JavaScriptIndexingBehavior":["double"],"List":["double"],"JavaScriptObject":[],"EfficientLengthIterable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"TrustedGetRuntimeType":[],"ListBase.E":"double"},"NativeFloat64List":{"ListBase":["double"],"Float64List":[],"JavaScriptIndexingBehavior":["double"],"List":["double"],"JavaScriptObject":[],"EfficientLengthIterable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"TrustedGetRuntimeType":[],"ListBase.E":"double"},"NativeInt16List":{"ListBase":["int"],"Int16List":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int"},"NativeInt32List":{"ListBase":["int"],"Int32List":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int"},"NativeInt8List":{"ListBase":["int"],"Int8List":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int"},"NativeUint16List":{"ListBase":["int"],"Uint16List":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int"},"NativeUint32List":{"ListBase":["int"],"Uint32List":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int"},"NativeUint8ClampedList":{"ListBase":["int"],"Uint8ClampedList":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int"},"NativeUint8List":{"ListBase":["int"],"Uint8List":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"JavaScriptObject":[],"EfficientLengthIterable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"TrustedGetRuntimeType":[],"ListBase.E":"int"},"_Error":{"Error":[]},"_TypeError":{"TypeError":[],"Error":[]},"AsyncError":{"Error":[]},"_Future":{"Future":["1"]},"_TimerImpl":{"Timer":[]},"_Completer":{"Completer":["1"]},"_AsyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_SyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_StreamController":{"StreamController":["1"],"StreamSink":["1"],"StreamConsumer":["1"],"_StreamControllerLifecycle":["1"],"_EventDispatch":["1"]},"_SyncStreamController":{"_SyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"StreamSink":["1"],"StreamConsumer":["1"],"_StreamControllerLifecycle":["1"],"_EventDispatch":["1"]},"_ControllerStream":{"_StreamImpl":["1"],"Stream":["1"],"Stream.T":"1"},"_ControllerSubscription":{"_BufferingStreamSubscription":["1"],"StreamSubscription":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamSinkWrapper":{"StreamSink":["1"],"StreamConsumer":["1"]},"_BufferingStreamSubscription":{"StreamSubscription":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamImpl":{"Stream":["1"]},"_DelayedData":{"_DelayedEvent":["1"]},"_DelayedError":{"_DelayedEvent":["@"]},"_DelayedDone":{"_DelayedEvent":["@"]},"_DoneStreamSubscription":{"StreamSubscription":["1"]},"_EmptyStream":{"Stream":["1"],"Stream.T":"1"},"_ZoneSpecification":{"ZoneSpecification":[]},"_ZoneDelegate":{"ZoneDelegate":[]},"_Zone":{"Zone":[]},"_CustomZone":{"_Zone":[],"Zone":[]},"_RootZone":{"_Zone":[],"Zone":[]},"_HashMap":{"MapBase":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_IdentityHashMap":{"_HashMap":["1","2"],"MapBase":["1","2"],"Map":["1","2"],"MapBase.K":"1","MapBase.V":"2"},"_HashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"_HashMapKeyIterator":{"Iterator":["1"]},"_LinkedHashSet":{"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_LinkedHashSetIterator":{"Iterator":["1"]},"ListBase":{"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"MapBase":{"Map":["1","2"]},"MapView":{"Map":["1","2"]},"UnmodifiableMapView":{"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"SetBase":{"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_SetBase":{"SetBase":["1"],"Set":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_JsonMap":{"MapBase":["String","@"],"Map":["String","@"],"MapBase.K":"String","MapBase.V":"@"},"_JsonMapKeyIterable":{"ListIterable":["String"],"EfficientLengthIterable":["String"],"Iterable":["String"],"ListIterable.E":"String","Iterable.E":"String"},"AsciiCodec":{"Codec":["String","List<int>"]},"_UnicodeSubsetEncoder":{"Converter":["String","List<int>"],"StreamTransformer":["String","List<int>"]},"AsciiEncoder":{"Converter":["String","List<int>"],"StreamTransformer":["String","List<int>"]},"Base64Codec":{"Codec":["List<int>","String"]},"Base64Encoder":{"Converter":["List<int>","String"],"StreamTransformer":["List<int>","String"]},"_FusedCodec":{"Codec":["1","3"]},"Converter":{"StreamTransformer":["1","2"]},"Encoding":{"Codec":["String","List<int>"]},"JsonUnsupportedObjectError":{"Error":[]},"JsonCyclicError":{"Error":[]},"JsonCodec":{"Codec":["Object?","String"]},"JsonEncoder":{"Converter":["Object?","String"],"StreamTransformer":["Object?","String"]},"JsonDecoder":{"Converter":["String","Object?"],"StreamTransformer":["String","Object?"]},"Utf8Codec":{"Codec":["String","List<int>"]},"Utf8Encoder":{"Converter":["String","List<int>"],"StreamTransformer":["String","List<int>"]},"Utf8Decoder":{"Converter":["List<int>","String"],"StreamTransformer":["List<int>","String"]},"double":{"num":[]},"int":{"num":[]},"List":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"RegExpMatch":{"Match":[]},"String":{"Pattern":[]},"AssertionError":{"Error":[]},"TypeError":{"Error":[]},"ArgumentError":{"Error":[]},"RangeError":{"Error":[]},"IndexError":{"Error":[]},"NoSuchMethodError":{"Error":[]},"UnsupportedError":{"Error":[]},"UnimplementedError":{"Error":[]},"StateError":{"Error":[]},"ConcurrentModificationError":{"Error":[]},"OutOfMemoryError":{"Error":[]},"StackOverflowError":{"Error":[]},"_Exception":{"Exception":[]},"FormatException":{"Exception":[]},"_StringStackTrace":{"StackTrace":[]},"StringBuffer":{"StringSink":[]},"_Uri":{"Uri":[]},"_SimpleUri":{"Uri":[]},"_DataUri":{"Uri":[]},"CssRule":{"JavaScriptObject":[]},"File":{"JavaScriptObject":[]},"Gamepad":{"JavaScriptObject":[]},"MimeType":{"JavaScriptObject":[]},"Node":{"JavaScriptObject":[]},"Plugin":{"JavaScriptObject":[]},"SourceBuffer":{"JavaScriptObject":[]},"SpeechGrammar":{"JavaScriptObject":[]},"SpeechRecognitionResult":{"JavaScriptObject":[]},"StyleSheet":{"JavaScriptObject":[]},"TextTrack":{"JavaScriptObject":[]},"TextTrackCue":{"JavaScriptObject":[]},"Touch":{"JavaScriptObject":[]},"HtmlElement":{"Node":[],"JavaScriptObject":[]},"AccessibleNodeList":{"JavaScriptObject":[]},"AnchorElement":{"Node":[],"JavaScriptObject":[]},"AreaElement":{"Node":[],"JavaScriptObject":[]},"Blob":{"JavaScriptObject":[]},"CharacterData":{"Node":[],"JavaScriptObject":[]},"CssPerspective":{"JavaScriptObject":[]},"CssStyleDeclaration":{"JavaScriptObject":[]},"CssStyleValue":{"JavaScriptObject":[]},"CssTransformComponent":{"JavaScriptObject":[]},"CssTransformValue":{"JavaScriptObject":[]},"CssUnparsedValue":{"JavaScriptObject":[]},"DataTransferItemList":{"JavaScriptObject":[]},"DomException":{"JavaScriptObject":[]},"DomRectList":{"ListBase":["Rectangle<num>"],"ImmutableListMixin":["Rectangle<num>"],"List":["Rectangle<num>"],"JavaScriptIndexingBehavior":["Rectangle<num>"],"JavaScriptObject":[],"EfficientLengthIterable":["Rectangle<num>"],"Iterable":["Rectangle<num>"],"ImmutableListMixin.E":"Rectangle<num>","ListBase.E":"Rectangle<num>"},"DomRectReadOnly":{"JavaScriptObject":[],"Rectangle":["num"]},"DomStringList":{"ListBase":["String"],"ImmutableListMixin":["String"],"List":["String"],"JavaScriptIndexingBehavior":["String"],"JavaScriptObject":[],"EfficientLengthIterable":["String"],"Iterable":["String"],"ImmutableListMixin.E":"String","ListBase.E":"String"},"DomTokenList":{"JavaScriptObject":[]},"Element":{"Node":[],"JavaScriptObject":[]},"EventTarget":{"JavaScriptObject":[]},"FileList":{"ListBase":["File"],"ImmutableListMixin":["File"],"List":["File"],"JavaScriptIndexingBehavior":["File"],"JavaScriptObject":[],"EfficientLengthIterable":["File"],"Iterable":["File"],"ImmutableListMixin.E":"File","ListBase.E":"File"},"FileWriter":{"JavaScriptObject":[]},"FormElement":{"Node":[],"JavaScriptObject":[]},"History":{"JavaScriptObject":[]},"HtmlCollection":{"ListBase":["Node"],"ImmutableListMixin":["Node"],"List":["Node"],"JavaScriptIndexingBehavior":["Node"],"JavaScriptObject":[],"EfficientLengthIterable":["Node"],"Iterable":["Node"],"ImmutableListMixin.E":"Node","ListBase.E":"Node"},"Location":{"JavaScriptObject":[]},"MediaList":{"JavaScriptObject":[]},"MidiInputMap":{"JavaScriptObject":[],"MapBase":["String","@"],"Map":["String","@"],"MapBase.K":"String","MapBase.V":"@"},"MidiOutputMap":{"JavaScriptObject":[],"MapBase":["String","@"],"Map":["String","@"],"MapBase.K":"String","MapBase.V":"@"},"MimeTypeArray":{"ListBase":["MimeType"],"ImmutableListMixin":["MimeType"],"List":["MimeType"],"JavaScriptIndexingBehavior":["MimeType"],"JavaScriptObject":[],"EfficientLengthIterable":["MimeType"],"Iterable":["MimeType"],"ImmutableListMixin.E":"MimeType","ListBase.E":"MimeType"},"NodeList":{"ListBase":["Node"],"ImmutableListMixin":["Node"],"List":["Node"],"JavaScriptIndexingBehavior":["Node"],"JavaScriptObject":[],"EfficientLengthIterable":["Node"],"Iterable":["Node"],"ImmutableListMixin.E":"Node","ListBase.E":"Node"},"PluginArray":{"ListBase":["Plugin"],"ImmutableListMixin":["Plugin"],"List":["Plugin"],"JavaScriptIndexingBehavior":["Plugin"],"JavaScriptObject":[],"EfficientLengthIterable":["Plugin"],"Iterable":["Plugin"],"ImmutableListMixin.E":"Plugin","ListBase.E":"Plugin"},"RtcStatsReport":{"JavaScriptObject":[],"MapBase":["String","@"],"Map":["String","@"],"MapBase.K":"String","MapBase.V":"@"},"SelectElement":{"Node":[],"JavaScriptObject":[]},"SourceBufferList":{"ListBase":["SourceBuffer"],"ImmutableListMixin":["SourceBuffer"],"List":["SourceBuffer"],"JavaScriptIndexingBehavior":["SourceBuffer"],"JavaScriptObject":[],"EfficientLengthIterable":["SourceBuffer"],"Iterable":["SourceBuffer"],"ImmutableListMixin.E":"SourceBuffer","ListBase.E":"SourceBuffer"},"SpeechGrammarList":{"ListBase":["SpeechGrammar"],"ImmutableListMixin":["SpeechGrammar"],"List":["SpeechGrammar"],"JavaScriptIndexingBehavior":["SpeechGrammar"],"JavaScriptObject":[],"EfficientLengthIterable":["SpeechGrammar"],"Iterable":["SpeechGrammar"],"ImmutableListMixin.E":"SpeechGrammar","ListBase.E":"SpeechGrammar"},"Storage":{"JavaScriptObject":[],"MapBase":["String","String"],"Map":["String","String"],"MapBase.K":"String","MapBase.V":"String"},"TextTrackCueList":{"ListBase":["TextTrackCue"],"ImmutableListMixin":["TextTrackCue"],"List":["TextTrackCue"],"JavaScriptIndexingBehavior":["TextTrackCue"],"JavaScriptObject":[],"EfficientLengthIterable":["TextTrackCue"],"Iterable":["TextTrackCue"],"ImmutableListMixin.E":"TextTrackCue","ListBase.E":"TextTrackCue"},"TextTrackList":{"ListBase":["TextTrack"],"ImmutableListMixin":["TextTrack"],"List":["TextTrack"],"JavaScriptIndexingBehavior":["TextTrack"],"JavaScriptObject":[],"EfficientLengthIterable":["TextTrack"],"Iterable":["TextTrack"],"ImmutableListMixin.E":"TextTrack","ListBase.E":"TextTrack"},"TimeRanges":{"JavaScriptObject":[]},"TouchList":{"ListBase":["Touch"],"ImmutableListMixin":["Touch"],"List":["Touch"],"JavaScriptIndexingBehavior":["Touch"],"JavaScriptObject":[],"EfficientLengthIterable":["Touch"],"Iterable":["Touch"],"ImmutableListMixin.E":"Touch","ListBase.E":"Touch"},"TrackDefaultList":{"JavaScriptObject":[]},"Url":{"JavaScriptObject":[]},"VideoTrackList":{"JavaScriptObject":[]},"_CssRuleList":{"ListBase":["CssRule"],"ImmutableListMixin":["CssRule"],"List":["CssRule"],"JavaScriptIndexingBehavior":["CssRule"],"JavaScriptObject":[],"EfficientLengthIterable":["CssRule"],"Iterable":["CssRule"],"ImmutableListMixin.E":"CssRule","ListBase.E":"CssRule"},"_DomRect":{"JavaScriptObject":[],"Rectangle":["num"]},"_GamepadList":{"ListBase":["Gamepad?"],"ImmutableListMixin":["Gamepad?"],"List":["Gamepad?"],"JavaScriptIndexingBehavior":["Gamepad?"],"JavaScriptObject":[],"EfficientLengthIterable":["Gamepad?"],"Iterable":["Gamepad?"],"ImmutableListMixin.E":"Gamepad?","ListBase.E":"Gamepad?"},"_NamedNodeMap":{"ListBase":["Node"],"ImmutableListMixin":["Node"],"List":["Node"],"JavaScriptIndexingBehavior":["Node"],"JavaScriptObject":[],"EfficientLengthIterable":["Node"],"Iterable":["Node"],"ImmutableListMixin.E":"Node","ListBase.E":"Node"},"_SpeechRecognitionResultList":{"ListBase":["SpeechRecognitionResult"],"ImmutableListMixin":["SpeechRecognitionResult"],"List":["SpeechRecognitionResult"],"JavaScriptIndexingBehavior":["SpeechRecognitionResult"],"JavaScriptObject":[],"EfficientLengthIterable":["SpeechRecognitionResult"],"Iterable":["SpeechRecognitionResult"],"ImmutableListMixin.E":"SpeechRecognitionResult","ListBase.E":"SpeechRecognitionResult"},"_StyleSheetList":{"ListBase":["StyleSheet"],"ImmutableListMixin":["StyleSheet"],"List":["StyleSheet"],"JavaScriptIndexingBehavior":["StyleSheet"],"JavaScriptObject":[],"EfficientLengthIterable":["StyleSheet"],"Iterable":["StyleSheet"],"ImmutableListMixin.E":"StyleSheet","ListBase.E":"StyleSheet"},"FixedSizeListIterator":{"Iterator":["1"]},"NullRejectionException":{"Exception":[]},"Length":{"JavaScriptObject":[]},"Number":{"JavaScriptObject":[]},"Transform":{"JavaScriptObject":[]},"LengthList":{"ListBase":["Length"],"ImmutableListMixin":["Length"],"List":["Length"],"JavaScriptObject":[],"EfficientLengthIterable":["Length"],"Iterable":["Length"],"ImmutableListMixin.E":"Length","ListBase.E":"Length"},"NumberList":{"ListBase":["Number"],"ImmutableListMixin":["Number"],"List":["Number"],"JavaScriptObject":[],"EfficientLengthIterable":["Number"],"Iterable":["Number"],"ImmutableListMixin.E":"Number","ListBase.E":"Number"},"PointList":{"JavaScriptObject":[]},"StringList":{"ListBase":["String"],"ImmutableListMixin":["String"],"List":["String"],"JavaScriptObject":[],"EfficientLengthIterable":["String"],"Iterable":["String"],"ImmutableListMixin.E":"String","ListBase.E":"String"},"TransformList":{"ListBase":["Transform"],"ImmutableListMixin":["Transform"],"List":["Transform"],"JavaScriptObject":[],"EfficientLengthIterable":["Transform"],"Iterable":["Transform"],"ImmutableListMixin.E":"Transform","ListBase.E":"Transform"},"AudioBuffer":{"JavaScriptObject":[]},"AudioParamMap":{"JavaScriptObject":[],"MapBase":["String","@"],"Map":["String","@"],"MapBase.K":"String","MapBase.V":"@"},"AudioTrackList":{"JavaScriptObject":[]},"BaseAudioContext":{"JavaScriptObject":[]},"OfflineAudioContext":{"JavaScriptObject":[]},"NullStreamSink":{"StreamSink":["1"],"StreamConsumer":["1"]},"PathException":{"Exception":[]},"PosixStyle":{"InternalStyle":[]},"UrlStyle":{"InternalStyle":[]},"WindowsStyle":{"InternalStyle":[]},"Chain":{"StackTrace":[]},"LazyTrace":{"Trace":[],"StackTrace":[]},"Trace":{"StackTrace":[]},"UnparsedFrame":{"Frame":[]},"GuaranteeChannel":{"StreamChannelMixin":["1"],"StreamChannel":["1"]},"_GuaranteeSink":{"StreamSink":["1"],"StreamConsumer":["1"]},"_MultiChannel":{"StreamChannelMixin":["1"],"MultiChannel":["1"],"StreamChannel":["1"]},"VirtualChannel":{"StreamChannelMixin":["1"],"MultiChannel":["1"],"StreamChannel":["1"]},"StreamChannelMixin":{"StreamChannel":["1"]},"Int8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8ClampedList":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Float32List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]},"Float64List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]}}'));
+  A._Universe_addErasedTypes(init.typeUniverse, JSON.parse('{"UnmodifiableListBase":1,"__CastListBase__CastIterableBase_ListMixin":2,"NativeTypedArray":1,"_DelayedEvent":1,"_SetBase":1}'));
   var string$ = {
-    ______: "===== asynchronous gap ===========================\n",
+    x27_has_: "' has been assigned during initialization.",
+    x3d_____: "===== asynchronous gap ===========================\n",
     Cannotff: "Cannot extract a file path from a URI with a fragment component",
     Cannotfq: "Cannot extract a file path from a URI with a query component",
     Cannotn: "Cannot extract a non-Windows file path from a file URI with an authority",
@@ -16698,6 +17692,8 @@
     var findType = A.findType;
     return {
       AsyncError: findType("AsyncError"),
+      ByteBuffer: findType("ByteBuffer"),
+      ByteData: findType("ByteData"),
       ConstantMapView_Symbol_dynamic: findType("ConstantMapView<Symbol0,@>"),
       CssRule: findType("CssRule"),
       Duration: findType("Duration"),
@@ -16705,22 +17701,24 @@
       Error: findType("Error"),
       Exception: findType("Exception"),
       File: findType("File"),
+      Float32List: findType("Float32List"),
+      Float64List: findType("Float64List"),
       Frame: findType("Frame"),
       Frame_Function_Frame: findType("Frame(Frame)"),
       Frame_Function_String: findType("Frame(String)"),
       Function: findType("Function"),
       Future_dynamic: findType("Future<@>"),
-      Future_void: findType("Future<~>"),
-      InternalStyle: findType("InternalStyle"),
+      Int16List: findType("Int16List"),
+      Int32List: findType("Int32List"),
+      Int8List: findType("Int8List"),
       Invocation: findType("Invocation"),
       Iterable_String: findType("Iterable<String>"),
       Iterable_dynamic: findType("Iterable<@>"),
+      Iterable_nullable_Object: findType("Iterable<Object?>"),
       JSArray_Frame: findType("JSArray<Frame>"),
       JSArray_JavaScriptObject: findType("JSArray<JavaScriptObject>"),
       JSArray_Object: findType("JSArray<Object>"),
-      JSArray_StreamSubscription_void: findType("JSArray<StreamSubscription<~>>"),
       JSArray_String: findType("JSArray<String>"),
-      JSArray_Subscription: findType("JSArray<Subscription>"),
       JSArray_Trace: findType("JSArray<Trace>"),
       JSArray_Uint8List: findType("JSArray<Uint8List>"),
       JSArray_dynamic: findType("JSArray<@>"),
@@ -16737,6 +17735,7 @@
       List_int: findType("List<int>"),
       Map_String_String: findType("Map<String,String>"),
       Map_dynamic_dynamic: findType("Map<@,@>"),
+      Map_of_nullable_Object_and_nullable_Object: findType("Map<Object?,Object?>"),
       MappedIterable_String_Frame: findType("MappedIterable<String,Frame>"),
       MappedListIterable_Frame_Frame: findType("MappedListIterable<Frame,Frame>"),
       MappedListIterable_String_Trace: findType("MappedListIterable<String,Trace>"),
@@ -16747,8 +17746,8 @@
       Null: findType("Null"),
       Number: findType("Number"),
       Object: findType("Object"),
-      Pattern: findType("Pattern"),
       Plugin: findType("Plugin"),
+      Record: findType("Record"),
       Rectangle_num: findType("Rectangle<num>"),
       RegExpMatch: findType("RegExpMatch"),
       SourceBuffer: findType("SourceBuffer"),
@@ -16765,7 +17764,11 @@
       Trace: findType("Trace"),
       Trace_Function_String: findType("Trace(String)"),
       Transform: findType("Transform"),
+      TrustedGetRuntimeType: findType("TrustedGetRuntimeType"),
       TypeError: findType("TypeError"),
+      Uint16List: findType("Uint16List"),
+      Uint32List: findType("Uint32List"),
+      Uint8ClampedList: findType("Uint8ClampedList"),
       Uint8List: findType("Uint8List"),
       UnknownJavaScriptObject: findType("UnknownJavaScriptObject"),
       UnmodifiableMapView_String_String: findType("UnmodifiableMapView<String,String>"),
@@ -16777,7 +17780,7 @@
       _Future_dynamic: findType("_Future<@>"),
       _Future_int: findType("_Future<int>"),
       _Future_void: findType("_Future<~>"),
-      _IdentityHashMap_dynamic_dynamic: findType("_IdentityHashMap<@,@>"),
+      _IdentityHashMap_of_nullable_Object_and_nullable_Object: findType("_IdentityHashMap<Object?,Object?>"),
       _StreamControllerAddStreamState_nullable_Object: findType("_StreamControllerAddStreamState<Object?>"),
       _SyncCompleter_dynamic: findType("_SyncCompleter<@>"),
       _ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_Object_StackTrace: findType("_ZoneFunction<~(Zone,ZoneDelegate,Zone,Object,StackTrace)>"),
@@ -16807,8 +17810,6 @@
       nullable__DelayedEvent_dynamic: findType("_DelayedEvent<@>?"),
       nullable__FutureListener_dynamic_dynamic: findType("_FutureListener<@,@>?"),
       nullable__LinkedHashSetCell: findType("_LinkedHashSetCell?"),
-      nullable_nullable_Object_Function_2_nullable_Object_and_nullable_Object: findType("Object?(Object?,Object?)?"),
-      nullable_nullable_Object_Function_dynamic: findType("Object?(@)?"),
       nullable_void_Function: findType("~()?"),
       num: findType("num"),
       void: findType("~"),
@@ -16971,27 +17972,38 @@
     B.Duration_0 = new A.Duration(0);
     B.JsonDecoder_null = new A.JsonDecoder(null);
     B.JsonEncoder_null = new A.JsonEncoder(null);
-    B.List_2Vk = A._setArrayType(makeConstList([0, 0, 32776, 33792, 1, 10240, 0, 0]), type$.JSArray_int);
-    B.List_CVk = A._setArrayType(makeConstList([0, 0, 65490, 45055, 65535, 34815, 65534, 18431]), type$.JSArray_int);
-    B.List_JYB = A._setArrayType(makeConstList([0, 0, 26624, 1023, 65534, 2047, 65534, 2047]), type$.JSArray_int);
+    B.List_M1A = A._setArrayType(makeConstList([0, 0, 24576, 1023, 65534, 34815, 65534, 18431]), type$.JSArray_int);
+    B.List_MMm = A._setArrayType(makeConstList([0, 0, 26624, 1023, 65534, 2047, 65534, 2047]), type$.JSArray_int);
+    B.List_OL3 = A._setArrayType(makeConstList([0, 0, 32722, 12287, 65534, 34815, 65534, 18431]), type$.JSArray_int);
+    B.List_XRg0 = A._setArrayType(makeConstList([0, 0, 32722, 12287, 65535, 34815, 65534, 18431]), type$.JSArray_int);
+    B.List_XRg = A._setArrayType(makeConstList([0, 0, 65490, 12287, 65535, 34815, 65534, 18431]), type$.JSArray_int);
+    B.List_YmH = A._setArrayType(makeConstList([0, 0, 32776, 33792, 1, 10240, 0, 0]), type$.JSArray_int);
+    B.List_ejq = A._setArrayType(makeConstList([0, 0, 32754, 11263, 65534, 34815, 65534, 18431]), type$.JSArray_int);
     B.List_empty = A._setArrayType(makeConstList([]), type$.JSArray_String);
     B.List_empty0 = A._setArrayType(makeConstList([]), type$.JSArray_dynamic);
-    B.List_gRj = A._setArrayType(makeConstList([0, 0, 32722, 12287, 65534, 34815, 65534, 18431]), type$.JSArray_int);
-    B.List_nxB = A._setArrayType(makeConstList([0, 0, 24576, 1023, 65534, 34815, 65534, 18431]), type$.JSArray_int);
-    B.List_qFt = A._setArrayType(makeConstList([0, 0, 27858, 1023, 65534, 51199, 65535, 32767]), type$.JSArray_int);
-    B.List_qNA = A._setArrayType(makeConstList([0, 0, 32754, 11263, 65534, 34815, 65534, 18431]), type$.JSArray_int);
-    B.List_qg40 = A._setArrayType(makeConstList([0, 0, 32722, 12287, 65535, 34815, 65534, 18431]), type$.JSArray_int);
-    B.List_qg4 = A._setArrayType(makeConstList([0, 0, 65490, 12287, 65535, 34815, 65534, 18431]), type$.JSArray_int);
-    B.Map_empty = new A.ConstantStringMap(0, {}, B.List_empty, A.findType("ConstantStringMap<String,String>"));
-    B.List_empty1 = A._setArrayType(makeConstList([]), A.findType("JSArray<Symbol0>"));
-    B.Map_empty0 = new A.ConstantStringMap(0, {}, B.List_empty1, A.findType("ConstantStringMap<Symbol0,@>"));
+    B.List_oFp = A._setArrayType(makeConstList([0, 0, 65490, 45055, 65535, 34815, 65534, 18431]), type$.JSArray_int);
+    B.List_yzX = A._setArrayType(makeConstList([0, 0, 27858, 1023, 65534, 51199, 65535, 32767]), type$.JSArray_int);
+    B.Object_empty = {};
+    B.Map_empty = new A.ConstantStringMap(B.Object_empty, [], A.findType("ConstantStringMap<String,String>"));
+    B.Map_empty0 = new A.ConstantStringMap(B.Object_empty, [], A.findType("ConstantStringMap<Symbol0,@>"));
     B.Symbol_call = new A.Symbol("call");
+    B.Type_ByteBuffer_RkP = A.typeLiteral("ByteBuffer");
+    B.Type_ByteData_zNC = A.typeLiteral("ByteData");
+    B.Type_Float32List_LB7 = A.typeLiteral("Float32List");
+    B.Type_Float64List_LB7 = A.typeLiteral("Float64List");
+    B.Type_Int16List_uXf = A.typeLiteral("Int16List");
+    B.Type_Int32List_O50 = A.typeLiteral("Int32List");
+    B.Type_Int8List_ekJ = A.typeLiteral("Int8List");
     B.Type_Object_xQ6 = A.typeLiteral("Object");
+    B.Type_Uint16List_2bx = A.typeLiteral("Uint16List");
+    B.Type_Uint32List_2bx = A.typeLiteral("Uint32List");
+    B.Type_Uint8ClampedList_Jik = A.typeLiteral("Uint8ClampedList");
+    B.Type_Uint8List_WLA = A.typeLiteral("Uint8List");
     B.Utf8Decoder_false = new A.Utf8Decoder(false);
     B._StringStackTrace_3uE = new A._StringStackTrace("");
     B._ZoneFunction_3bB = new A._ZoneFunction(B.C__RootZone, A.async___rootCreatePeriodicTimer$closure(), A.findType("_ZoneFunction<Timer(Zone,ZoneDelegate,Zone,Duration,~(Timer))>"));
-    B._ZoneFunction_7G2 = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterBinaryCallback$closure(), A.findType("_ZoneFunction<0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))<Object?Object?Object?>>"));
-    B._ZoneFunction_Eeh = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterUnaryCallback$closure(), A.findType("_ZoneFunction<0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))<Object?Object?>>"));
+    B._ZoneFunction_7G2 = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterBinaryCallback$closure(), A.findType("_ZoneFunction<0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))<Object?,Object?,Object?>>"));
+    B._ZoneFunction_Eeh = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterUnaryCallback$closure(), A.findType("_ZoneFunction<0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))<Object?,Object?>>"));
     B._ZoneFunction_NMc = new A._ZoneFunction(B.C__RootZone, A.async___rootHandleUncaughtError$closure(), type$._ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_Object_StackTrace);
     B._ZoneFunction__RootZone__rootCreateTimer = new A._ZoneFunction(B.C__RootZone, A.async___rootCreateTimer$closure(), A.findType("_ZoneFunction<Timer(Zone,ZoneDelegate,Zone,Duration,~())>"));
     B._ZoneFunction__RootZone__rootErrorCallback = new A._ZoneFunction(B.C__RootZone, A.async___rootErrorCallback$closure(), A.findType("_ZoneFunction<AsyncError?(Zone,ZoneDelegate,Zone,Object,StackTrace?)>"));
@@ -16999,12 +18011,13 @@
     B._ZoneFunction__RootZone__rootPrint = new A._ZoneFunction(B.C__RootZone, A.async___rootPrint$closure(), A.findType("_ZoneFunction<~(Zone,ZoneDelegate,Zone,String)>"));
     B._ZoneFunction__RootZone__rootRegisterCallback = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterCallback$closure(), A.findType("_ZoneFunction<0^()(Zone,ZoneDelegate,Zone,0^())<Object?>>"));
     B._ZoneFunction__RootZone__rootRun = new A._ZoneFunction(B.C__RootZone, A.async___rootRun$closure(), A.findType("_ZoneFunction<0^(Zone,ZoneDelegate,Zone,0^())<Object?>>"));
-    B._ZoneFunction__RootZone__rootRunBinary = new A._ZoneFunction(B.C__RootZone, A.async___rootRunBinary$closure(), A.findType("_ZoneFunction<0^(Zone,ZoneDelegate,Zone,0^(1^,2^),1^,2^)<Object?Object?Object?>>"));
-    B._ZoneFunction__RootZone__rootRunUnary = new A._ZoneFunction(B.C__RootZone, A.async___rootRunUnary$closure(), A.findType("_ZoneFunction<0^(Zone,ZoneDelegate,Zone,0^(1^),1^)<Object?Object?>>"));
+    B._ZoneFunction__RootZone__rootRunBinary = new A._ZoneFunction(B.C__RootZone, A.async___rootRunBinary$closure(), A.findType("_ZoneFunction<0^(Zone,ZoneDelegate,Zone,0^(1^,2^),1^,2^)<Object?,Object?,Object?>>"));
+    B._ZoneFunction__RootZone__rootRunUnary = new A._ZoneFunction(B.C__RootZone, A.async___rootRunUnary$closure(), A.findType("_ZoneFunction<0^(Zone,ZoneDelegate,Zone,0^(1^),1^)<Object?,Object?>>"));
     B._ZoneFunction__RootZone__rootScheduleMicrotask = new A._ZoneFunction(B.C__RootZone, A.async___rootScheduleMicrotask$closure(), A.findType("_ZoneFunction<~(Zone,ZoneDelegate,Zone,~())>"));
   })();
   (function staticFields() {
     $._JS_INTEROP_INTERCEPTOR_TAG = null;
+    $.toStringVisiting = A._setArrayType([], type$.JSArray_Object);
     $.printToZone = null;
     $.Primitives__identityHashCodeProperty = null;
     $.BoundClosure__receiverFieldNameCache = null;
@@ -17021,12 +18034,13 @@
     $._isInCallbackLoop = false;
     $.Zone__current = B.C__RootZone;
     $._RootZone__rootDelegate = null;
-    $._toStringVisiting = A._setArrayType([], type$.JSArray_Object);
+    $.Uri__cachedBaseString = "";
+    $.Uri__cachedBaseUri = null;
     $._currentUriBase = null;
     $._current = null;
     $._iframes = A.LinkedHashMap_LinkedHashMap$_empty(type$.int, type$.JavaScriptObject);
-    $._subscriptions = A.LinkedHashMap_LinkedHashMap$_empty(type$.int, A.findType("List<StreamSubscription<~>>"));
-    $._domSubscriptions = A.LinkedHashMap_LinkedHashMap$_empty(type$.int, A.findType("List<Subscription>"));
+    $._subscriptions = A.LinkedHashMap_LinkedHashMap$_empty(type$.int, A.findType("StreamSubscription<~>"));
+    $._domSubscriptions = A.LinkedHashMap_LinkedHashMap$_empty(type$.int, A.findType("Subscription"));
   })();
   (function lazyInitializers() {
     var _lazyFinal = hunkHelpers.lazyFinal;
@@ -17090,7 +18104,7 @@
     _lazyFinal($, "_hashSeed", "$get$_hashSeed", () => A.objectHashCode(B.Type_Object_xQ6));
     _lazyFinal($, "_scannerTables", "$get$_scannerTables", () => A._createTables());
     _lazyFinal($, "windows", "$get$windows", () => A.Context_Context($.$get$Style_windows()));
-    _lazyFinal($, "context", "$get$context", () => new A.Context(type$.InternalStyle._as($.$get$Style_platform()), null));
+    _lazyFinal($, "context", "$get$context", () => new A.Context($.$get$Style_platform(), null));
     _lazyFinal($, "Style_posix", "$get$Style_posix", () => new A.PosixStyle(A.RegExp_RegExp("/", false), A.RegExp_RegExp("[^/]$", false), A.RegExp_RegExp("^/", false)));
     _lazyFinal($, "Style_windows", "$get$Style_windows", () => new A.WindowsStyle(A.RegExp_RegExp("[/\\\\]", false), A.RegExp_RegExp("[^/\\\\]$", false), A.RegExp_RegExp("^(\\\\\\\\[^\\\\]+\\\\[^\\\\/]+|[a-zA-Z]:[/\\\\])", false), A.RegExp_RegExp("^[/\\\\](?![/\\\\])", false)));
     _lazyFinal($, "Style_url", "$get$Style_url", () => new A.UrlStyle(A.RegExp_RegExp("/", false), A.RegExp_RegExp("(^[a-zA-Z][-+.a-zA-Z\\d]*://|[^/])$", false), A.RegExp_RegExp("[a-zA-Z][-+.a-zA-Z\\d]*://[^/]*", false), A.RegExp_RegExp("^/", false)));
@@ -17113,7 +18127,7 @@
     _lazyFinal($, "_firefoxSafariTrace", "$get$_firefoxSafariTrace", () => A.RegExp_RegExp("^(([.0-9A-Za-z_$/<]|\\(.*\\))*@)?[^\\s]*:\\d*$", true));
     _lazyFinal($, "_friendlyTrace", "$get$_friendlyTrace", () => A.RegExp_RegExp("^[^\\s<][^\\s]*( \\d+(:\\d+)?)?[ \\t]+[^\\s]+$", true));
     _lazyFinal($, "vmChainGap", "$get$vmChainGap", () => A.RegExp_RegExp("^<asynchronous suspension>\\n?$", true));
-    _lazyFinal($, "_currentUrl", "$get$_currentUrl", () => A.Uri_parse(A.getProperty(A.WindowExtension_get_location(self.window), "href", type$.String)));
+    _lazyFinal($, "_currentUrl", "$get$_currentUrl", () => A.Uri_parse(A.getProperty(A.getProperty(self.window, "location", type$.JavaScriptObject), "href", type$.String)));
   })();
   (function nativeSupport() {
     !function() {
@@ -17138,8 +18152,8 @@
       }
       init.dispatchPropertyName = init.getIsolateTag("dispatch_record");
     }();
-    hunkHelpers.setOrUpdateInterceptorsByTag({ArrayBuffer: J.Interceptor, WebGL: J.Interceptor, AbortPaymentEvent: J.JavaScriptObject, AnimationEffectReadOnly: J.JavaScriptObject, AnimationEffectTiming: J.JavaScriptObject, AnimationEffectTimingReadOnly: J.JavaScriptObject, AnimationEvent: J.JavaScriptObject, AnimationPlaybackEvent: J.JavaScriptObject, AnimationTimeline: J.JavaScriptObject, AnimationWorkletGlobalScope: J.JavaScriptObject, ApplicationCacheErrorEvent: J.JavaScriptObject, AuthenticatorAssertionResponse: J.JavaScriptObject, AuthenticatorAttestationResponse: J.JavaScriptObject, AuthenticatorResponse: J.JavaScriptObject, BackgroundFetchClickEvent: J.JavaScriptObject, BackgroundFetchEvent: J.JavaScriptObject, BackgroundFetchFailEvent: J.JavaScriptObject, BackgroundFetchFetch: J.JavaScriptObject, BackgroundFetchManager: J.JavaScriptObject, BackgroundFetchSettledFetch: J.JavaScriptObject, BackgroundFetchedEvent: J.JavaScriptObject, BarProp: J.JavaScriptObject, BarcodeDetector: J.JavaScriptObject, BeforeInstallPromptEvent: J.JavaScriptObject, BeforeUnloadEvent: J.JavaScriptObject, BlobEvent: J.JavaScriptObject, BluetoothRemoteGATTDescriptor: J.JavaScriptObject, Body: J.JavaScriptObject, BudgetState: J.JavaScriptObject, CacheStorage: J.JavaScriptObject, CanMakePaymentEvent: J.JavaScriptObject, CanvasGradient: J.JavaScriptObject, CanvasPattern: J.JavaScriptObject, CanvasRenderingContext2D: J.JavaScriptObject, Client: J.JavaScriptObject, Clients: J.JavaScriptObject, ClipboardEvent: J.JavaScriptObject, CloseEvent: J.JavaScriptObject, CompositionEvent: J.JavaScriptObject, CookieStore: J.JavaScriptObject, Coordinates: J.JavaScriptObject, Credential: J.JavaScriptObject, CredentialUserData: J.JavaScriptObject, CredentialsContainer: J.JavaScriptObject, Crypto: J.JavaScriptObject, CryptoKey: J.JavaScriptObject, CSS: J.JavaScriptObject, CSSVariableReferenceValue: J.JavaScriptObject, CustomElementRegistry: J.JavaScriptObject, CustomEvent: J.JavaScriptObject, DataTransfer: J.JavaScriptObject, DataTransferItem: J.JavaScriptObject, DeprecatedStorageInfo: J.JavaScriptObject, DeprecatedStorageQuota: J.JavaScriptObject, DeprecationReport: J.JavaScriptObject, DetectedBarcode: J.JavaScriptObject, DetectedFace: J.JavaScriptObject, DetectedText: J.JavaScriptObject, DeviceAcceleration: J.JavaScriptObject, DeviceMotionEvent: J.JavaScriptObject, DeviceOrientationEvent: J.JavaScriptObject, DeviceRotationRate: J.JavaScriptObject, DirectoryEntry: J.JavaScriptObject, webkitFileSystemDirectoryEntry: J.JavaScriptObject, FileSystemDirectoryEntry: J.JavaScriptObject, DirectoryReader: J.JavaScriptObject, WebKitDirectoryReader: J.JavaScriptObject, webkitFileSystemDirectoryReader: J.JavaScriptObject, FileSystemDirectoryReader: J.JavaScriptObject, DocumentOrShadowRoot: J.JavaScriptObject, DocumentTimeline: J.JavaScriptObject, DOMError: J.JavaScriptObject, DOMImplementation: J.JavaScriptObject, Iterator: J.JavaScriptObject, DOMMatrix: J.JavaScriptObject, DOMMatrixReadOnly: J.JavaScriptObject, DOMParser: J.JavaScriptObject, DOMPoint: J.JavaScriptObject, DOMPointReadOnly: J.JavaScriptObject, DOMQuad: J.JavaScriptObject, DOMStringMap: J.JavaScriptObject, Entry: J.JavaScriptObject, webkitFileSystemEntry: J.JavaScriptObject, FileSystemEntry: J.JavaScriptObject, ErrorEvent: J.JavaScriptObject, Event: J.JavaScriptObject, InputEvent: J.JavaScriptObject, SubmitEvent: J.JavaScriptObject, ExtendableEvent: J.JavaScriptObject, ExtendableMessageEvent: J.JavaScriptObject, External: J.JavaScriptObject, FaceDetector: J.JavaScriptObject, FederatedCredential: J.JavaScriptObject, FetchEvent: J.JavaScriptObject, FileEntry: J.JavaScriptObject, webkitFileSystemFileEntry: J.JavaScriptObject, FileSystemFileEntry: J.JavaScriptObject, DOMFileSystem: J.JavaScriptObject, WebKitFileSystem: J.JavaScriptObject, webkitFileSystem: J.JavaScriptObject, FileSystem: J.JavaScriptObject, FocusEvent: J.JavaScriptObject, FontFace: J.JavaScriptObject, FontFaceSetLoadEvent: J.JavaScriptObject, FontFaceSource: J.JavaScriptObject, ForeignFetchEvent: J.JavaScriptObject, FormData: J.JavaScriptObject, GamepadButton: J.JavaScriptObject, GamepadEvent: J.JavaScriptObject, GamepadPose: J.JavaScriptObject, Geolocation: J.JavaScriptObject, Position: J.JavaScriptObject, GeolocationPosition: J.JavaScriptObject, HashChangeEvent: J.JavaScriptObject, Headers: J.JavaScriptObject, HTMLHyperlinkElementUtils: J.JavaScriptObject, IdleDeadline: J.JavaScriptObject, ImageBitmap: J.JavaScriptObject, ImageBitmapRenderingContext: J.JavaScriptObject, ImageCapture: J.JavaScriptObject, ImageData: J.JavaScriptObject, InputDeviceCapabilities: J.JavaScriptObject, InstallEvent: J.JavaScriptObject, IntersectionObserver: J.JavaScriptObject, IntersectionObserverEntry: J.JavaScriptObject, InterventionReport: J.JavaScriptObject, KeyboardEvent: J.JavaScriptObject, KeyframeEffect: J.JavaScriptObject, KeyframeEffectReadOnly: J.JavaScriptObject, MediaCapabilities: J.JavaScriptObject, MediaCapabilitiesInfo: J.JavaScriptObject, MediaDeviceInfo: J.JavaScriptObject, MediaEncryptedEvent: J.JavaScriptObject, MediaError: J.JavaScriptObject, MediaKeyMessageEvent: J.JavaScriptObject, MediaKeyStatusMap: J.JavaScriptObject, MediaKeySystemAccess: J.JavaScriptObject, MediaKeys: J.JavaScriptObject, MediaKeysPolicy: J.JavaScriptObject, MediaMetadata: J.JavaScriptObject, MediaQueryListEvent: J.JavaScriptObject, MediaSession: J.JavaScriptObject, MediaSettingsRange: J.JavaScriptObject, MediaStreamEvent: J.JavaScriptObject, MediaStreamTrackEvent: J.JavaScriptObject, MemoryInfo: J.JavaScriptObject, MessageChannel: J.JavaScriptObject, MessageEvent: J.JavaScriptObject, Metadata: J.JavaScriptObject, MIDIConnectionEvent: J.JavaScriptObject, MIDIMessageEvent: J.JavaScriptObject, MouseEvent: J.JavaScriptObject, DragEvent: J.JavaScriptObject, MutationEvent: J.JavaScriptObject, MutationObserver: J.JavaScriptObject, WebKitMutationObserver: J.JavaScriptObject, MutationRecord: J.JavaScriptObject, NavigationPreloadManager: J.JavaScriptObject, Navigator: J.JavaScriptObject, NavigatorAutomationInformation: J.JavaScriptObject, NavigatorConcurrentHardware: J.JavaScriptObject, NavigatorCookies: J.JavaScriptObject, NavigatorUserMediaError: J.JavaScriptObject, NodeFilter: J.JavaScriptObject, NodeIterator: J.JavaScriptObject, NonDocumentTypeChildNode: J.JavaScriptObject, NonElementParentNode: J.JavaScriptObject, NoncedElement: J.JavaScriptObject, NotificationEvent: J.JavaScriptObject, OffscreenCanvasRenderingContext2D: J.JavaScriptObject, OverconstrainedError: J.JavaScriptObject, PageTransitionEvent: J.JavaScriptObject, PaintRenderingContext2D: J.JavaScriptObject, PaintSize: J.JavaScriptObject, PaintWorkletGlobalScope: J.JavaScriptObject, PasswordCredential: J.JavaScriptObject, Path2D: J.JavaScriptObject, PaymentAddress: J.JavaScriptObject, PaymentInstruments: J.JavaScriptObject, PaymentManager: J.JavaScriptObject, PaymentRequestEvent: J.JavaScriptObject, PaymentRequestUpdateEvent: J.JavaScriptObject, PaymentResponse: J.JavaScriptObject, PerformanceEntry: J.JavaScriptObject, PerformanceLongTaskTiming: J.JavaScriptObject, PerformanceMark: J.JavaScriptObject, PerformanceMeasure: J.JavaScriptObject, PerformanceNavigation: J.JavaScriptObject, PerformanceNavigationTiming: J.JavaScriptObject, PerformanceObserver: J.JavaScriptObject, PerformanceObserverEntryList: J.JavaScriptObject, PerformancePaintTiming: J.JavaScriptObject, PerformanceResourceTiming: J.JavaScriptObject, PerformanceServerTiming: J.JavaScriptObject, PerformanceTiming: J.JavaScriptObject, Permissions: J.JavaScriptObject, PhotoCapabilities: J.JavaScriptObject, PointerEvent: J.JavaScriptObject, PopStateEvent: J.JavaScriptObject, PositionError: J.JavaScriptObject, GeolocationPositionError: J.JavaScriptObject, Presentation: J.JavaScriptObject, PresentationConnectionAvailableEvent: J.JavaScriptObject, PresentationConnectionCloseEvent: J.JavaScriptObject, PresentationReceiver: J.JavaScriptObject, ProgressEvent: J.JavaScriptObject, PromiseRejectionEvent: J.JavaScriptObject, PublicKeyCredential: J.JavaScriptObject, PushEvent: J.JavaScriptObject, PushManager: J.JavaScriptObject, PushMessageData: J.JavaScriptObject, PushSubscription: J.JavaScriptObject, PushSubscriptionOptions: J.JavaScriptObject, Range: J.JavaScriptObject, RelatedApplication: J.JavaScriptObject, ReportBody: J.JavaScriptObject, ReportingObserver: J.JavaScriptObject, ResizeObserver: J.JavaScriptObject, ResizeObserverEntry: J.JavaScriptObject, RTCCertificate: J.JavaScriptObject, RTCDataChannelEvent: J.JavaScriptObject, RTCDTMFToneChangeEvent: J.JavaScriptObject, RTCIceCandidate: J.JavaScriptObject, mozRTCIceCandidate: J.JavaScriptObject, RTCLegacyStatsReport: J.JavaScriptObject, RTCPeerConnectionIceEvent: J.JavaScriptObject, RTCRtpContributingSource: J.JavaScriptObject, RTCRtpReceiver: J.JavaScriptObject, RTCRtpSender: J.JavaScriptObject, RTCSessionDescription: J.JavaScriptObject, mozRTCSessionDescription: J.JavaScriptObject, RTCStatsResponse: J.JavaScriptObject, RTCTrackEvent: J.JavaScriptObject, Screen: J.JavaScriptObject, ScrollState: J.JavaScriptObject, ScrollTimeline: J.JavaScriptObject, SecurityPolicyViolationEvent: J.JavaScriptObject, Selection: J.JavaScriptObject, SensorErrorEvent: J.JavaScriptObject, SharedArrayBuffer: J.JavaScriptObject, SpeechRecognitionAlternative: J.JavaScriptObject, SpeechRecognitionError: J.JavaScriptObject, SpeechRecognitionEvent: J.JavaScriptObject, SpeechSynthesisEvent: J.JavaScriptObject, SpeechSynthesisVoice: J.JavaScriptObject, StaticRange: J.JavaScriptObject, StorageEvent: J.JavaScriptObject, StorageManager: J.JavaScriptObject, StyleMedia: J.JavaScriptObject, StylePropertyMap: J.JavaScriptObject, StylePropertyMapReadonly: J.JavaScriptObject, SyncEvent: J.JavaScriptObject, SyncManager: J.JavaScriptObject, TaskAttributionTiming: J.JavaScriptObject, TextDetector: J.JavaScriptObject, TextEvent: J.JavaScriptObject, TextMetrics: J.JavaScriptObject, TouchEvent: J.JavaScriptObject, TrackDefault: J.JavaScriptObject, TrackEvent: J.JavaScriptObject, TransitionEvent: J.JavaScriptObject, WebKitTransitionEvent: J.JavaScriptObject, TreeWalker: J.JavaScriptObject, TrustedHTML: J.JavaScriptObject, TrustedScriptURL: J.JavaScriptObject, TrustedURL: J.JavaScriptObject, UIEvent: J.JavaScriptObject, UnderlyingSourceBase: J.JavaScriptObject, URLSearchParams: J.JavaScriptObject, VRCoordinateSystem: J.JavaScriptObject, VRDeviceEvent: J.JavaScriptObject, VRDisplayCapabilities: J.JavaScriptObject, VRDisplayEvent: J.JavaScriptObject, VREyeParameters: J.JavaScriptObject, VRFrameData: J.JavaScriptObject, VRFrameOfReference: J.JavaScriptObject, VRPose: J.JavaScriptObject, VRSessionEvent: J.JavaScriptObject, VRStageBounds: J.JavaScriptObject, VRStageBoundsPoint: J.JavaScriptObject, VRStageParameters: J.JavaScriptObject, ValidityState: J.JavaScriptObject, VideoPlaybackQuality: J.JavaScriptObject, VideoTrack: J.JavaScriptObject, VTTRegion: J.JavaScriptObject, WheelEvent: J.JavaScriptObject, WindowClient: J.JavaScriptObject, WorkletAnimation: J.JavaScriptObject, WorkletGlobalScope: J.JavaScriptObject, XPathEvaluator: J.JavaScriptObject, XPathExpression: J.JavaScriptObject, XPathNSResolver: J.JavaScriptObject, XPathResult: J.JavaScriptObject, XMLSerializer: J.JavaScriptObject, XSLTProcessor: J.JavaScriptObject, Bluetooth: J.JavaScriptObject, BluetoothCharacteristicProperties: J.JavaScriptObject, BluetoothRemoteGATTServer: J.JavaScriptObject, BluetoothRemoteGATTService: J.JavaScriptObject, BluetoothUUID: J.JavaScriptObject, BudgetService: J.JavaScriptObject, Cache: J.JavaScriptObject, DOMFileSystemSync: J.JavaScriptObject, DirectoryEntrySync: J.JavaScriptObject, DirectoryReaderSync: J.JavaScriptObject, EntrySync: J.JavaScriptObject, FileEntrySync: J.JavaScriptObject, FileReaderSync: J.JavaScriptObject, FileWriterSync: J.JavaScriptObject, HTMLAllCollection: J.JavaScriptObject, Mojo: J.JavaScriptObject, MojoHandle: J.JavaScriptObject, MojoInterfaceRequestEvent: J.JavaScriptObject, MojoWatcher: J.JavaScriptObject, NFC: J.JavaScriptObject, PagePopupController: J.JavaScriptObject, Report: J.JavaScriptObject, Request: J.JavaScriptObject, ResourceProgressEvent: J.JavaScriptObject, Response: J.JavaScriptObject, SubtleCrypto: J.JavaScriptObject, USBAlternateInterface: J.JavaScriptObject, USBConfiguration: J.JavaScriptObject, USBConnectionEvent: J.JavaScriptObject, USBDevice: J.JavaScriptObject, USBEndpoint: J.JavaScriptObject, USBInTransferResult: J.JavaScriptObject, USBInterface: J.JavaScriptObject, USBIsochronousInTransferPacket: J.JavaScriptObject, USBIsochronousInTransferResult: J.JavaScriptObject, USBIsochronousOutTransferPacket: J.JavaScriptObject, USBIsochronousOutTransferResult: J.JavaScriptObject, USBOutTransferResult: J.JavaScriptObject, WorkerLocation: J.JavaScriptObject, WorkerNavigator: J.JavaScriptObject, Worklet: J.JavaScriptObject, IDBCursor: J.JavaScriptObject, IDBCursorWithValue: J.JavaScriptObject, IDBFactory: J.JavaScriptObject, IDBIndex: J.JavaScriptObject, IDBKeyRange: J.JavaScriptObject, IDBObjectStore: J.JavaScriptObject, IDBObservation: J.JavaScriptObject, IDBObserver: J.JavaScriptObject, IDBObserverChanges: J.JavaScriptObject, IDBVersionChangeEvent: J.JavaScriptObject, SVGAngle: J.JavaScriptObject, SVGAnimatedAngle: J.JavaScriptObject, SVGAnimatedBoolean: J.JavaScriptObject, SVGAnimatedEnumeration: J.JavaScriptObject, SVGAnimatedInteger: J.JavaScriptObject, SVGAnimatedLength: J.JavaScriptObject, SVGAnimatedLengthList: J.JavaScriptObject, SVGAnimatedNumber: J.JavaScriptObject, SVGAnimatedNumberList: J.JavaScriptObject, SVGAnimatedPreserveAspectRatio: J.JavaScriptObject, SVGAnimatedRect: J.JavaScriptObject, SVGAnimatedString: J.JavaScriptObject, SVGAnimatedTransformList: J.JavaScriptObject, SVGMatrix: J.JavaScriptObject, SVGPoint: J.JavaScriptObject, SVGPreserveAspectRatio: J.JavaScriptObject, SVGRect: J.JavaScriptObject, SVGUnitTypes: J.JavaScriptObject, AudioListener: J.JavaScriptObject, AudioParam: J.JavaScriptObject, AudioProcessingEvent: J.JavaScriptObject, AudioTrack: J.JavaScriptObject, AudioWorkletGlobalScope: J.JavaScriptObject, AudioWorkletProcessor: J.JavaScriptObject, OfflineAudioCompletionEvent: J.JavaScriptObject, PeriodicWave: J.JavaScriptObject, WebGLActiveInfo: J.JavaScriptObject, ANGLEInstancedArrays: J.JavaScriptObject, ANGLE_instanced_arrays: J.JavaScriptObject, WebGLBuffer: J.JavaScriptObject, WebGLCanvas: J.JavaScriptObject, WebGLColorBufferFloat: J.JavaScriptObject, WebGLCompressedTextureASTC: J.JavaScriptObject, WebGLCompressedTextureATC: J.JavaScriptObject, WEBGL_compressed_texture_atc: J.JavaScriptObject, WebGLCompressedTextureETC1: J.JavaScriptObject, WEBGL_compressed_texture_etc1: J.JavaScriptObject, WebGLCompressedTextureETC: J.JavaScriptObject, WebGLCompressedTexturePVRTC: J.JavaScriptObject, WEBGL_compressed_texture_pvrtc: J.JavaScriptObject, WebGLCompressedTextureS3TC: J.JavaScriptObject, WEBGL_compressed_texture_s3tc: J.JavaScriptObject, WebGLCompressedTextureS3TCsRGB: J.JavaScriptObject, WebGLContextEvent: J.JavaScriptObject, WebGLDebugRendererInfo: J.JavaScriptObject, WEBGL_debug_renderer_info: J.JavaScriptObject, WebGLDebugShaders: J.JavaScriptObject, WEBGL_debug_shaders: J.JavaScriptObject, WebGLDepthTexture: J.JavaScriptObject, WEBGL_depth_texture: J.JavaScriptObject, WebGLDrawBuffers: J.JavaScriptObject, WEBGL_draw_buffers: J.JavaScriptObject, EXTsRGB: J.JavaScriptObject, EXT_sRGB: J.JavaScriptObject, EXTBlendMinMax: J.JavaScriptObject, EXT_blend_minmax: J.JavaScriptObject, EXTColorBufferFloat: J.JavaScriptObject, EXTColorBufferHalfFloat: J.JavaScriptObject, EXTDisjointTimerQuery: J.JavaScriptObject, EXTDisjointTimerQueryWebGL2: J.JavaScriptObject, EXTFragDepth: J.JavaScriptObject, EXT_frag_depth: J.JavaScriptObject, EXTShaderTextureLOD: J.JavaScriptObject, EXT_shader_texture_lod: J.JavaScriptObject, EXTTextureFilterAnisotropic: J.JavaScriptObject, EXT_texture_filter_anisotropic: J.JavaScriptObject, WebGLFramebuffer: J.JavaScriptObject, WebGLGetBufferSubDataAsync: J.JavaScriptObject, WebGLLoseContext: J.JavaScriptObject, WebGLExtensionLoseContext: J.JavaScriptObject, WEBGL_lose_context: J.JavaScriptObject, OESElementIndexUint: J.JavaScriptObject, OES_element_index_uint: J.JavaScriptObject, OESStandardDerivatives: J.JavaScriptObject, OES_standard_derivatives: J.JavaScriptObject, OESTextureFloat: J.JavaScriptObject, OES_texture_float: J.JavaScriptObject, OESTextureFloatLinear: J.JavaScriptObject, OES_texture_float_linear: J.JavaScriptObject, OESTextureHalfFloat: J.JavaScriptObject, OES_texture_half_float: J.JavaScriptObject, OESTextureHalfFloatLinear: J.JavaScriptObject, OES_texture_half_float_linear: J.JavaScriptObject, OESVertexArrayObject: J.JavaScriptObject, OES_vertex_array_object: J.JavaScriptObject, WebGLProgram: J.JavaScriptObject, WebGLQuery: J.JavaScriptObject, WebGLRenderbuffer: J.JavaScriptObject, WebGLRenderingContext: J.JavaScriptObject, WebGL2RenderingContext: J.JavaScriptObject, WebGLSampler: J.JavaScriptObject, WebGLShader: J.JavaScriptObject, WebGLShaderPrecisionFormat: J.JavaScriptObject, WebGLSync: J.JavaScriptObject, WebGLTexture: J.JavaScriptObject, WebGLTimerQueryEXT: J.JavaScriptObject, WebGLTransformFeedback: J.JavaScriptObject, WebGLUniformLocation: J.JavaScriptObject, WebGLVertexArrayObject: J.JavaScriptObject, WebGLVertexArrayObjectOES: J.JavaScriptObject, WebGL2RenderingContextBase: J.JavaScriptObject, DataView: A.NativeTypedData, ArrayBufferView: A.NativeTypedData, Float32Array: A.NativeTypedArrayOfDouble, Float64Array: A.NativeTypedArrayOfDouble, Int16Array: A.NativeInt16List, Int32Array: A.NativeInt32List, Int8Array: A.NativeInt8List, Uint16Array: A.NativeUint16List, Uint32Array: A.NativeUint32List, Uint8ClampedArray: A.NativeUint8ClampedList, CanvasPixelArray: A.NativeUint8ClampedList, Uint8Array: A.NativeUint8List, HTMLAudioElement: A.HtmlElement, HTMLBRElement: A.HtmlElement, HTMLBaseElement: A.HtmlElement, HTMLBodyElement: A.HtmlElement, HTMLButtonElement: A.HtmlElement, HTMLCanvasElement: A.HtmlElement, HTMLContentElement: A.HtmlElement, HTMLDListElement: A.HtmlElement, HTMLDataElement: A.HtmlElement, HTMLDataListElement: A.HtmlElement, HTMLDetailsElement: A.HtmlElement, HTMLDialogElement: A.HtmlElement, HTMLDivElement: A.HtmlElement, HTMLEmbedElement: A.HtmlElement, HTMLFieldSetElement: A.HtmlElement, HTMLHRElement: A.HtmlElement, HTMLHeadElement: A.HtmlElement, HTMLHeadingElement: A.HtmlElement, HTMLHtmlElement: A.HtmlElement, HTMLIFrameElement: A.HtmlElement, HTMLImageElement: A.HtmlElement, HTMLInputElement: A.HtmlElement, HTMLLIElement: A.HtmlElement, HTMLLabelElement: A.HtmlElement, HTMLLegendElement: A.HtmlElement, HTMLLinkElement: A.HtmlElement, HTMLMapElement: A.HtmlElement, HTMLMediaElement: A.HtmlElement, HTMLMenuElement: A.HtmlElement, HTMLMetaElement: A.HtmlElement, HTMLMeterElement: A.HtmlElement, HTMLModElement: A.HtmlElement, HTMLOListElement: A.HtmlElement, HTMLObjectElement: A.HtmlElement, HTMLOptGroupElement: A.HtmlElement, HTMLOptionElement: A.HtmlElement, HTMLOutputElement: A.HtmlElement, HTMLParagraphElement: A.HtmlElement, HTMLParamElement: A.HtmlElement, HTMLPictureElement: A.HtmlElement, HTMLPreElement: A.HtmlElement, HTMLProgressElement: A.HtmlElement, HTMLQuoteElement: A.HtmlElement, HTMLScriptElement: A.HtmlElement, HTMLShadowElement: A.HtmlElement, HTMLSlotElement: A.HtmlElement, HTMLSourceElement: A.HtmlElement, HTMLSpanElement: A.HtmlElement, HTMLStyleElement: A.HtmlElement, HTMLTableCaptionElement: A.HtmlElement, HTMLTableCellElement: A.HtmlElement, HTMLTableDataCellElement: A.HtmlElement, HTMLTableHeaderCellElement: A.HtmlElement, HTMLTableColElement: A.HtmlElement, HTMLTableElement: A.HtmlElement, HTMLTableRowElement: A.HtmlElement, HTMLTableSectionElement: A.HtmlElement, HTMLTemplateElement: A.HtmlElement, HTMLTextAreaElement: A.HtmlElement, HTMLTimeElement: A.HtmlElement, HTMLTitleElement: A.HtmlElement, HTMLTrackElement: A.HtmlElement, HTMLUListElement: A.HtmlElement, HTMLUnknownElement: A.HtmlElement, HTMLVideoElement: A.HtmlElement, HTMLDirectoryElement: A.HtmlElement, HTMLFontElement: A.HtmlElement, HTMLFrameElement: A.HtmlElement, HTMLFrameSetElement: A.HtmlElement, HTMLMarqueeElement: A.HtmlElement, HTMLElement: A.HtmlElement, AccessibleNodeList: A.AccessibleNodeList, HTMLAnchorElement: A.AnchorElement, HTMLAreaElement: A.AreaElement, Blob: A.Blob, CDATASection: A.CharacterData, CharacterData: A.CharacterData, Comment: A.CharacterData, ProcessingInstruction: A.CharacterData, Text: A.CharacterData, CSSPerspective: A.CssPerspective, CSSCharsetRule: A.CssRule, CSSConditionRule: A.CssRule, CSSFontFaceRule: A.CssRule, CSSGroupingRule: A.CssRule, CSSImportRule: A.CssRule, CSSKeyframeRule: A.CssRule, MozCSSKeyframeRule: A.CssRule, WebKitCSSKeyframeRule: A.CssRule, CSSKeyframesRule: A.CssRule, MozCSSKeyframesRule: A.CssRule, WebKitCSSKeyframesRule: A.CssRule, CSSMediaRule: A.CssRule, CSSNamespaceRule: A.CssRule, CSSPageRule: A.CssRule, CSSRule: A.CssRule, CSSStyleRule: A.CssRule, CSSSupportsRule: A.CssRule, CSSViewportRule: A.CssRule, CSSStyleDeclaration: A.CssStyleDeclaration, MSStyleCSSProperties: A.CssStyleDeclaration, CSS2Properties: A.CssStyleDeclaration, CSSImageValue: A.CssStyleValue, CSSKeywordValue: A.CssStyleValue, CSSNumericValue: A.CssStyleValue, CSSPositionValue: A.CssStyleValue, CSSResourceValue: A.CssStyleValue, CSSUnitValue: A.CssStyleValue, CSSURLImageValue: A.CssStyleValue, CSSStyleValue: A.CssStyleValue, CSSMatrixComponent: A.CssTransformComponent, CSSRotation: A.CssTransformComponent, CSSScale: A.CssTransformComponent, CSSSkew: A.CssTransformComponent, CSSTranslation: A.CssTransformComponent, CSSTransformComponent: A.CssTransformComponent, CSSTransformValue: A.CssTransformValue, CSSUnparsedValue: A.CssUnparsedValue, DataTransferItemList: A.DataTransferItemList, DOMException: A.DomException, ClientRectList: A.DomRectList, DOMRectList: A.DomRectList, DOMRectReadOnly: A.DomRectReadOnly, DOMStringList: A.DomStringList, DOMTokenList: A.DomTokenList, MathMLElement: A.Element, SVGAElement: A.Element, SVGAnimateElement: A.Element, SVGAnimateMotionElement: A.Element, SVGAnimateTransformElement: A.Element, SVGAnimationElement: A.Element, SVGCircleElement: A.Element, SVGClipPathElement: A.Element, SVGDefsElement: A.Element, SVGDescElement: A.Element, SVGDiscardElement: A.Element, SVGEllipseElement: A.Element, SVGFEBlendElement: A.Element, SVGFEColorMatrixElement: A.Element, SVGFEComponentTransferElement: A.Element, SVGFECompositeElement: A.Element, SVGFEConvolveMatrixElement: A.Element, SVGFEDiffuseLightingElement: A.Element, SVGFEDisplacementMapElement: A.Element, SVGFEDistantLightElement: A.Element, SVGFEFloodElement: A.Element, SVGFEFuncAElement: A.Element, SVGFEFuncBElement: A.Element, SVGFEFuncGElement: A.Element, SVGFEFuncRElement: A.Element, SVGFEGaussianBlurElement: A.Element, SVGFEImageElement: A.Element, SVGFEMergeElement: A.Element, SVGFEMergeNodeElement: A.Element, SVGFEMorphologyElement: A.Element, SVGFEOffsetElement: A.Element, SVGFEPointLightElement: A.Element, SVGFESpecularLightingElement: A.Element, SVGFESpotLightElement: A.Element, SVGFETileElement: A.Element, SVGFETurbulenceElement: A.Element, SVGFilterElement: A.Element, SVGForeignObjectElement: A.Element, SVGGElement: A.Element, SVGGeometryElement: A.Element, SVGGraphicsElement: A.Element, SVGImageElement: A.Element, SVGLineElement: A.Element, SVGLinearGradientElement: A.Element, SVGMarkerElement: A.Element, SVGMaskElement: A.Element, SVGMetadataElement: A.Element, SVGPathElement: A.Element, SVGPatternElement: A.Element, SVGPolygonElement: A.Element, SVGPolylineElement: A.Element, SVGRadialGradientElement: A.Element, SVGRectElement: A.Element, SVGScriptElement: A.Element, SVGSetElement: A.Element, SVGStopElement: A.Element, SVGStyleElement: A.Element, SVGElement: A.Element, SVGSVGElement: A.Element, SVGSwitchElement: A.Element, SVGSymbolElement: A.Element, SVGTSpanElement: A.Element, SVGTextContentElement: A.Element, SVGTextElement: A.Element, SVGTextPathElement: A.Element, SVGTextPositioningElement: A.Element, SVGTitleElement: A.Element, SVGUseElement: A.Element, SVGViewElement: A.Element, SVGGradientElement: A.Element, SVGComponentTransferFunctionElement: A.Element, SVGFEDropShadowElement: A.Element, SVGMPathElement: A.Element, Element: A.Element, AbsoluteOrientationSensor: A.EventTarget, Accelerometer: A.EventTarget, AccessibleNode: A.EventTarget, AmbientLightSensor: A.EventTarget, Animation: A.EventTarget, ApplicationCache: A.EventTarget, DOMApplicationCache: A.EventTarget, OfflineResourceList: A.EventTarget, BackgroundFetchRegistration: A.EventTarget, BatteryManager: A.EventTarget, BroadcastChannel: A.EventTarget, CanvasCaptureMediaStreamTrack: A.EventTarget, DedicatedWorkerGlobalScope: A.EventTarget, EventSource: A.EventTarget, FileReader: A.EventTarget, FontFaceSet: A.EventTarget, Gyroscope: A.EventTarget, XMLHttpRequest: A.EventTarget, XMLHttpRequestEventTarget: A.EventTarget, XMLHttpRequestUpload: A.EventTarget, LinearAccelerationSensor: A.EventTarget, Magnetometer: A.EventTarget, MediaDevices: A.EventTarget, MediaKeySession: A.EventTarget, MediaQueryList: A.EventTarget, MediaRecorder: A.EventTarget, MediaSource: A.EventTarget, MediaStream: A.EventTarget, MediaStreamTrack: A.EventTarget, MessagePort: A.EventTarget, MIDIAccess: A.EventTarget, MIDIInput: A.EventTarget, MIDIOutput: A.EventTarget, MIDIPort: A.EventTarget, NetworkInformation: A.EventTarget, Notification: A.EventTarget, OffscreenCanvas: A.EventTarget, OrientationSensor: A.EventTarget, PaymentRequest: A.EventTarget, Performance: A.EventTarget, PermissionStatus: A.EventTarget, PresentationAvailability: A.EventTarget, PresentationConnection: A.EventTarget, PresentationConnectionList: A.EventTarget, PresentationRequest: A.EventTarget, RelativeOrientationSensor: A.EventTarget, RemotePlayback: A.EventTarget, RTCDataChannel: A.EventTarget, DataChannel: A.EventTarget, RTCDTMFSender: A.EventTarget, RTCPeerConnection: A.EventTarget, webkitRTCPeerConnection: A.EventTarget, mozRTCPeerConnection: A.EventTarget, ScreenOrientation: A.EventTarget, Sensor: A.EventTarget, ServiceWorker: A.EventTarget, ServiceWorkerContainer: A.EventTarget, ServiceWorkerGlobalScope: A.EventTarget, ServiceWorkerRegistration: A.EventTarget, SharedWorker: A.EventTarget, SharedWorkerGlobalScope: A.EventTarget, SpeechRecognition: A.EventTarget, SpeechSynthesis: A.EventTarget, SpeechSynthesisUtterance: A.EventTarget, VR: A.EventTarget, VRDevice: A.EventTarget, VRDisplay: A.EventTarget, VRSession: A.EventTarget, VisualViewport: A.EventTarget, WebSocket: A.EventTarget, Window: A.EventTarget, DOMWindow: A.EventTarget, Worker: A.EventTarget, WorkerGlobalScope: A.EventTarget, WorkerPerformance: A.EventTarget, BluetoothDevice: A.EventTarget, BluetoothRemoteGATTCharacteristic: A.EventTarget, Clipboard: A.EventTarget, MojoInterfaceInterceptor: A.EventTarget, USB: A.EventTarget, IDBDatabase: A.EventTarget, IDBOpenDBRequest: A.EventTarget, IDBVersionChangeRequest: A.EventTarget, IDBRequest: A.EventTarget, IDBTransaction: A.EventTarget, AnalyserNode: A.EventTarget, RealtimeAnalyserNode: A.EventTarget, AudioBufferSourceNode: A.EventTarget, AudioDestinationNode: A.EventTarget, AudioNode: A.EventTarget, AudioScheduledSourceNode: A.EventTarget, AudioWorkletNode: A.EventTarget, BiquadFilterNode: A.EventTarget, ChannelMergerNode: A.EventTarget, AudioChannelMerger: A.EventTarget, ChannelSplitterNode: A.EventTarget, AudioChannelSplitter: A.EventTarget, ConstantSourceNode: A.EventTarget, ConvolverNode: A.EventTarget, DelayNode: A.EventTarget, DynamicsCompressorNode: A.EventTarget, GainNode: A.EventTarget, AudioGainNode: A.EventTarget, IIRFilterNode: A.EventTarget, MediaElementAudioSourceNode: A.EventTarget, MediaStreamAudioDestinationNode: A.EventTarget, MediaStreamAudioSourceNode: A.EventTarget, OscillatorNode: A.EventTarget, Oscillator: A.EventTarget, PannerNode: A.EventTarget, AudioPannerNode: A.EventTarget, webkitAudioPannerNode: A.EventTarget, ScriptProcessorNode: A.EventTarget, JavaScriptAudioNode: A.EventTarget, StereoPannerNode: A.EventTarget, WaveShaperNode: A.EventTarget, EventTarget: A.EventTarget, File: A.File, FileList: A.FileList, FileWriter: A.FileWriter, HTMLFormElement: A.FormElement, Gamepad: A.Gamepad, History: A.History, HTMLCollection: A.HtmlCollection, HTMLFormControlsCollection: A.HtmlCollection, HTMLOptionsCollection: A.HtmlCollection, Location: A.Location, MediaList: A.MediaList, MIDIInputMap: A.MidiInputMap, MIDIOutputMap: A.MidiOutputMap, MimeType: A.MimeType, MimeTypeArray: A.MimeTypeArray, Document: A.Node, DocumentFragment: A.Node, HTMLDocument: A.Node, ShadowRoot: A.Node, XMLDocument: A.Node, Attr: A.Node, DocumentType: A.Node, Node: A.Node, NodeList: A.NodeList, RadioNodeList: A.NodeList, Plugin: A.Plugin, PluginArray: A.PluginArray, RTCStatsReport: A.RtcStatsReport, HTMLSelectElement: A.SelectElement, SourceBuffer: A.SourceBuffer, SourceBufferList: A.SourceBufferList, SpeechGrammar: A.SpeechGrammar, SpeechGrammarList: A.SpeechGrammarList, SpeechRecognitionResult: A.SpeechRecognitionResult, Storage: A.Storage, CSSStyleSheet: A.StyleSheet, StyleSheet: A.StyleSheet, TextTrack: A.TextTrack, TextTrackCue: A.TextTrackCue, VTTCue: A.TextTrackCue, TextTrackCueList: A.TextTrackCueList, TextTrackList: A.TextTrackList, TimeRanges: A.TimeRanges, Touch: A.Touch, TouchList: A.TouchList, TrackDefaultList: A.TrackDefaultList, URL: A.Url, VideoTrackList: A.VideoTrackList, CSSRuleList: A._CssRuleList, ClientRect: A._DomRect, DOMRect: A._DomRect, GamepadList: A._GamepadList, NamedNodeMap: A._NamedNodeMap, MozNamedAttrMap: A._NamedNodeMap, SpeechRecognitionResultList: A._SpeechRecognitionResultList, StyleSheetList: A._StyleSheetList, SVGLength: A.Length, SVGLengthList: A.LengthList, SVGNumber: A.Number, SVGNumberList: A.NumberList, SVGPointList: A.PointList, SVGStringList: A.StringList, SVGTransform: A.Transform, SVGTransformList: A.TransformList, AudioBuffer: A.AudioBuffer, AudioParamMap: A.AudioParamMap, AudioTrackList: A.AudioTrackList, AudioContext: A.BaseAudioContext, webkitAudioContext: A.BaseAudioContext, BaseAudioContext: A.BaseAudioContext, OfflineAudioContext: A.OfflineAudioContext});
-    hunkHelpers.setOrUpdateLeafTags({ArrayBuffer: true, WebGL: true, AbortPaymentEvent: true, AnimationEffectReadOnly: true, AnimationEffectTiming: true, AnimationEffectTimingReadOnly: true, AnimationEvent: true, AnimationPlaybackEvent: true, AnimationTimeline: true, AnimationWorkletGlobalScope: true, ApplicationCacheErrorEvent: true, AuthenticatorAssertionResponse: true, AuthenticatorAttestationResponse: true, AuthenticatorResponse: true, BackgroundFetchClickEvent: true, BackgroundFetchEvent: true, BackgroundFetchFailEvent: true, BackgroundFetchFetch: true, BackgroundFetchManager: true, BackgroundFetchSettledFetch: true, BackgroundFetchedEvent: true, BarProp: true, BarcodeDetector: true, BeforeInstallPromptEvent: true, BeforeUnloadEvent: true, BlobEvent: true, BluetoothRemoteGATTDescriptor: true, Body: true, BudgetState: true, CacheStorage: true, CanMakePaymentEvent: true, CanvasGradient: true, CanvasPattern: true, CanvasRenderingContext2D: true, Client: true, Clients: true, ClipboardEvent: true, CloseEvent: true, CompositionEvent: true, CookieStore: true, Coordinates: true, Credential: true, CredentialUserData: true, CredentialsContainer: true, Crypto: true, CryptoKey: true, CSS: true, CSSVariableReferenceValue: true, CustomElementRegistry: true, CustomEvent: true, DataTransfer: true, DataTransferItem: true, DeprecatedStorageInfo: true, DeprecatedStorageQuota: true, DeprecationReport: true, DetectedBarcode: true, DetectedFace: true, DetectedText: true, DeviceAcceleration: true, DeviceMotionEvent: true, DeviceOrientationEvent: true, DeviceRotationRate: true, DirectoryEntry: true, webkitFileSystemDirectoryEntry: true, FileSystemDirectoryEntry: true, DirectoryReader: true, WebKitDirectoryReader: true, webkitFileSystemDirectoryReader: true, FileSystemDirectoryReader: true, DocumentOrShadowRoot: true, DocumentTimeline: true, DOMError: true, DOMImplementation: true, Iterator: true, DOMMatrix: true, DOMMatrixReadOnly: true, DOMParser: true, DOMPoint: true, DOMPointReadOnly: true, DOMQuad: true, DOMStringMap: true, Entry: true, webkitFileSystemEntry: true, FileSystemEntry: true, ErrorEvent: true, Event: true, InputEvent: true, SubmitEvent: true, ExtendableEvent: true, ExtendableMessageEvent: true, External: true, FaceDetector: true, FederatedCredential: true, FetchEvent: true, FileEntry: true, webkitFileSystemFileEntry: true, FileSystemFileEntry: true, DOMFileSystem: true, WebKitFileSystem: true, webkitFileSystem: true, FileSystem: true, FocusEvent: true, FontFace: true, FontFaceSetLoadEvent: true, FontFaceSource: true, ForeignFetchEvent: true, FormData: true, GamepadButton: true, GamepadEvent: true, GamepadPose: true, Geolocation: true, Position: true, GeolocationPosition: true, HashChangeEvent: true, Headers: true, HTMLHyperlinkElementUtils: true, IdleDeadline: true, ImageBitmap: true, ImageBitmapRenderingContext: true, ImageCapture: true, ImageData: true, InputDeviceCapabilities: true, InstallEvent: true, IntersectionObserver: true, IntersectionObserverEntry: true, InterventionReport: true, KeyboardEvent: true, KeyframeEffect: true, KeyframeEffectReadOnly: true, MediaCapabilities: true, MediaCapabilitiesInfo: true, MediaDeviceInfo: true, MediaEncryptedEvent: true, MediaError: true, MediaKeyMessageEvent: true, MediaKeyStatusMap: true, MediaKeySystemAccess: true, MediaKeys: true, MediaKeysPolicy: true, MediaMetadata: true, MediaQueryListEvent: true, MediaSession: true, MediaSettingsRange: true, MediaStreamEvent: true, MediaStreamTrackEvent: true, MemoryInfo: true, MessageChannel: true, MessageEvent: true, Metadata: true, MIDIConnectionEvent: true, MIDIMessageEvent: true, MouseEvent: true, DragEvent: true, MutationEvent: true, MutationObserver: true, WebKitMutationObserver: true, MutationRecord: true, NavigationPreloadManager: true, Navigator: true, NavigatorAutomationInformation: true, NavigatorConcurrentHardware: true, NavigatorCookies: true, NavigatorUserMediaError: true, NodeFilter: true, NodeIterator: true, NonDocumentTypeChildNode: true, NonElementParentNode: true, NoncedElement: true, NotificationEvent: true, OffscreenCanvasRenderingContext2D: true, OverconstrainedError: true, PageTransitionEvent: true, PaintRenderingContext2D: true, PaintSize: true, PaintWorkletGlobalScope: true, PasswordCredential: true, Path2D: true, PaymentAddress: true, PaymentInstruments: true, PaymentManager: true, PaymentRequestEvent: true, PaymentRequestUpdateEvent: true, PaymentResponse: true, PerformanceEntry: true, PerformanceLongTaskTiming: true, PerformanceMark: true, PerformanceMeasure: true, PerformanceNavigation: true, PerformanceNavigationTiming: true, PerformanceObserver: true, PerformanceObserverEntryList: true, PerformancePaintTiming: true, PerformanceResourceTiming: true, PerformanceServerTiming: true, PerformanceTiming: true, Permissions: true, PhotoCapabilities: true, PointerEvent: true, PopStateEvent: true, PositionError: true, GeolocationPositionError: true, Presentation: true, PresentationConnectionAvailableEvent: true, PresentationConnectionCloseEvent: true, PresentationReceiver: true, ProgressEvent: true, PromiseRejectionEvent: true, PublicKeyCredential: true, PushEvent: true, PushManager: true, PushMessageData: true, PushSubscription: true, PushSubscriptionOptions: true, Range: true, RelatedApplication: true, ReportBody: true, ReportingObserver: true, ResizeObserver: true, ResizeObserverEntry: true, RTCCertificate: true, RTCDataChannelEvent: true, RTCDTMFToneChangeEvent: true, RTCIceCandidate: true, mozRTCIceCandidate: true, RTCLegacyStatsReport: true, RTCPeerConnectionIceEvent: true, RTCRtpContributingSource: true, RTCRtpReceiver: true, RTCRtpSender: true, RTCSessionDescription: true, mozRTCSessionDescription: true, RTCStatsResponse: true, RTCTrackEvent: true, Screen: true, ScrollState: true, ScrollTimeline: true, SecurityPolicyViolationEvent: true, Selection: true, SensorErrorEvent: true, SharedArrayBuffer: true, SpeechRecognitionAlternative: true, SpeechRecognitionError: true, SpeechRecognitionEvent: true, SpeechSynthesisEvent: true, SpeechSynthesisVoice: true, StaticRange: true, StorageEvent: true, StorageManager: true, StyleMedia: true, StylePropertyMap: true, StylePropertyMapReadonly: true, SyncEvent: true, SyncManager: true, TaskAttributionTiming: true, TextDetector: true, TextEvent: true, TextMetrics: true, TouchEvent: true, TrackDefault: true, TrackEvent: true, TransitionEvent: true, WebKitTransitionEvent: true, TreeWalker: true, TrustedHTML: true, TrustedScriptURL: true, TrustedURL: true, UIEvent: true, UnderlyingSourceBase: true, URLSearchParams: true, VRCoordinateSystem: true, VRDeviceEvent: true, VRDisplayCapabilities: true, VRDisplayEvent: true, VREyeParameters: true, VRFrameData: true, VRFrameOfReference: true, VRPose: true, VRSessionEvent: true, VRStageBounds: true, VRStageBoundsPoint: true, VRStageParameters: true, ValidityState: true, VideoPlaybackQuality: true, VideoTrack: true, VTTRegion: true, WheelEvent: true, WindowClient: true, WorkletAnimation: true, WorkletGlobalScope: true, XPathEvaluator: true, XPathExpression: true, XPathNSResolver: true, XPathResult: true, XMLSerializer: true, XSLTProcessor: true, Bluetooth: true, BluetoothCharacteristicProperties: true, BluetoothRemoteGATTServer: true, BluetoothRemoteGATTService: true, BluetoothUUID: true, BudgetService: true, Cache: true, DOMFileSystemSync: true, DirectoryEntrySync: true, DirectoryReaderSync: true, EntrySync: true, FileEntrySync: true, FileReaderSync: true, FileWriterSync: true, HTMLAllCollection: true, Mojo: true, MojoHandle: true, MojoInterfaceRequestEvent: true, MojoWatcher: true, NFC: true, PagePopupController: true, Report: true, Request: true, ResourceProgressEvent: true, Response: true, SubtleCrypto: true, USBAlternateInterface: true, USBConfiguration: true, USBConnectionEvent: true, USBDevice: true, USBEndpoint: true, USBInTransferResult: true, USBInterface: true, USBIsochronousInTransferPacket: true, USBIsochronousInTransferResult: true, USBIsochronousOutTransferPacket: true, USBIsochronousOutTransferResult: true, USBOutTransferResult: true, WorkerLocation: true, WorkerNavigator: true, Worklet: true, IDBCursor: true, IDBCursorWithValue: true, IDBFactory: true, IDBIndex: true, IDBKeyRange: true, IDBObjectStore: true, IDBObservation: true, IDBObserver: true, IDBObserverChanges: true, IDBVersionChangeEvent: true, SVGAngle: true, SVGAnimatedAngle: true, SVGAnimatedBoolean: true, SVGAnimatedEnumeration: true, SVGAnimatedInteger: true, SVGAnimatedLength: true, SVGAnimatedLengthList: true, SVGAnimatedNumber: true, SVGAnimatedNumberList: true, SVGAnimatedPreserveAspectRatio: true, SVGAnimatedRect: true, SVGAnimatedString: true, SVGAnimatedTransformList: true, SVGMatrix: true, SVGPoint: true, SVGPreserveAspectRatio: true, SVGRect: true, SVGUnitTypes: true, AudioListener: true, AudioParam: true, AudioProcessingEvent: true, AudioTrack: true, AudioWorkletGlobalScope: true, AudioWorkletProcessor: true, OfflineAudioCompletionEvent: true, PeriodicWave: true, WebGLActiveInfo: true, ANGLEInstancedArrays: true, ANGLE_instanced_arrays: true, WebGLBuffer: true, WebGLCanvas: true, WebGLColorBufferFloat: true, WebGLCompressedTextureASTC: true, WebGLCompressedTextureATC: true, WEBGL_compressed_texture_atc: true, WebGLCompressedTextureETC1: true, WEBGL_compressed_texture_etc1: true, WebGLCompressedTextureETC: true, WebGLCompressedTexturePVRTC: true, WEBGL_compressed_texture_pvrtc: true, WebGLCompressedTextureS3TC: true, WEBGL_compressed_texture_s3tc: true, WebGLCompressedTextureS3TCsRGB: true, WebGLContextEvent: true, WebGLDebugRendererInfo: true, WEBGL_debug_renderer_info: true, WebGLDebugShaders: true, WEBGL_debug_shaders: true, WebGLDepthTexture: true, WEBGL_depth_texture: true, WebGLDrawBuffers: true, WEBGL_draw_buffers: true, EXTsRGB: true, EXT_sRGB: true, EXTBlendMinMax: true, EXT_blend_minmax: true, EXTColorBufferFloat: true, EXTColorBufferHalfFloat: true, EXTDisjointTimerQuery: true, EXTDisjointTimerQueryWebGL2: true, EXTFragDepth: true, EXT_frag_depth: true, EXTShaderTextureLOD: true, EXT_shader_texture_lod: true, EXTTextureFilterAnisotropic: true, EXT_texture_filter_anisotropic: true, WebGLFramebuffer: true, WebGLGetBufferSubDataAsync: true, WebGLLoseContext: true, WebGLExtensionLoseContext: true, WEBGL_lose_context: true, OESElementIndexUint: true, OES_element_index_uint: true, OESStandardDerivatives: true, OES_standard_derivatives: true, OESTextureFloat: true, OES_texture_float: true, OESTextureFloatLinear: true, OES_texture_float_linear: true, OESTextureHalfFloat: true, OES_texture_half_float: true, OESTextureHalfFloatLinear: true, OES_texture_half_float_linear: true, OESVertexArrayObject: true, OES_vertex_array_object: true, WebGLProgram: true, WebGLQuery: true, WebGLRenderbuffer: true, WebGLRenderingContext: true, WebGL2RenderingContext: true, WebGLSampler: true, WebGLShader: true, WebGLShaderPrecisionFormat: true, WebGLSync: true, WebGLTexture: true, WebGLTimerQueryEXT: true, WebGLTransformFeedback: true, WebGLUniformLocation: true, WebGLVertexArrayObject: true, WebGLVertexArrayObjectOES: true, WebGL2RenderingContextBase: true, DataView: true, ArrayBufferView: false, Float32Array: true, Float64Array: true, Int16Array: true, Int32Array: true, Int8Array: true, Uint16Array: true, Uint32Array: true, Uint8ClampedArray: true, CanvasPixelArray: true, Uint8Array: false, HTMLAudioElement: true, HTMLBRElement: true, HTMLBaseElement: true, HTMLBodyElement: true, HTMLButtonElement: true, HTMLCanvasElement: true, HTMLContentElement: true, HTMLDListElement: true, HTMLDataElement: true, HTMLDataListElement: true, HTMLDetailsElement: true, HTMLDialogElement: true, HTMLDivElement: true, HTMLEmbedElement: true, HTMLFieldSetElement: true, HTMLHRElement: true, HTMLHeadElement: true, HTMLHeadingElement: true, HTMLHtmlElement: true, HTMLIFrameElement: true, HTMLImageElement: true, HTMLInputElement: true, HTMLLIElement: true, HTMLLabelElement: true, HTMLLegendElement: true, HTMLLinkElement: true, HTMLMapElement: true, HTMLMediaElement: true, HTMLMenuElement: true, HTMLMetaElement: true, HTMLMeterElement: true, HTMLModElement: true, HTMLOListElement: true, HTMLObjectElement: true, HTMLOptGroupElement: true, HTMLOptionElement: true, HTMLOutputElement: true, HTMLParagraphElement: true, HTMLParamElement: true, HTMLPictureElement: true, HTMLPreElement: true, HTMLProgressElement: true, HTMLQuoteElement: true, HTMLScriptElement: true, HTMLShadowElement: true, HTMLSlotElement: true, HTMLSourceElement: true, HTMLSpanElement: true, HTMLStyleElement: true, HTMLTableCaptionElement: true, HTMLTableCellElement: true, HTMLTableDataCellElement: true, HTMLTableHeaderCellElement: true, HTMLTableColElement: true, HTMLTableElement: true, HTMLTableRowElement: true, HTMLTableSectionElement: true, HTMLTemplateElement: true, HTMLTextAreaElement: true, HTMLTimeElement: true, HTMLTitleElement: true, HTMLTrackElement: true, HTMLUListElement: true, HTMLUnknownElement: true, HTMLVideoElement: true, HTMLDirectoryElement: true, HTMLFontElement: true, HTMLFrameElement: true, HTMLFrameSetElement: true, HTMLMarqueeElement: true, HTMLElement: false, AccessibleNodeList: true, HTMLAnchorElement: true, HTMLAreaElement: true, Blob: false, CDATASection: true, CharacterData: true, Comment: true, ProcessingInstruction: true, Text: true, CSSPerspective: true, CSSCharsetRule: true, CSSConditionRule: true, CSSFontFaceRule: true, CSSGroupingRule: true, CSSImportRule: true, CSSKeyframeRule: true, MozCSSKeyframeRule: true, WebKitCSSKeyframeRule: true, CSSKeyframesRule: true, MozCSSKeyframesRule: true, WebKitCSSKeyframesRule: true, CSSMediaRule: true, CSSNamespaceRule: true, CSSPageRule: true, CSSRule: true, CSSStyleRule: true, CSSSupportsRule: true, CSSViewportRule: true, CSSStyleDeclaration: true, MSStyleCSSProperties: true, CSS2Properties: true, CSSImageValue: true, CSSKeywordValue: true, CSSNumericValue: true, CSSPositionValue: true, CSSResourceValue: true, CSSUnitValue: true, CSSURLImageValue: true, CSSStyleValue: false, CSSMatrixComponent: true, CSSRotation: true, CSSScale: true, CSSSkew: true, CSSTranslation: true, CSSTransformComponent: false, CSSTransformValue: true, CSSUnparsedValue: true, DataTransferItemList: true, DOMException: true, ClientRectList: true, DOMRectList: true, DOMRectReadOnly: false, DOMStringList: true, DOMTokenList: true, MathMLElement: true, SVGAElement: true, SVGAnimateElement: true, SVGAnimateMotionElement: true, SVGAnimateTransformElement: true, SVGAnimationElement: true, SVGCircleElement: true, SVGClipPathElement: true, SVGDefsElement: true, SVGDescElement: true, SVGDiscardElement: true, SVGEllipseElement: true, SVGFEBlendElement: true, SVGFEColorMatrixElement: true, SVGFEComponentTransferElement: true, SVGFECompositeElement: true, SVGFEConvolveMatrixElement: true, SVGFEDiffuseLightingElement: true, SVGFEDisplacementMapElement: true, SVGFEDistantLightElement: true, SVGFEFloodElement: true, SVGFEFuncAElement: true, SVGFEFuncBElement: true, SVGFEFuncGElement: true, SVGFEFuncRElement: true, SVGFEGaussianBlurElement: true, SVGFEImageElement: true, SVGFEMergeElement: true, SVGFEMergeNodeElement: true, SVGFEMorphologyElement: true, SVGFEOffsetElement: true, SVGFEPointLightElement: true, SVGFESpecularLightingElement: true, SVGFESpotLightElement: true, SVGFETileElement: true, SVGFETurbulenceElement: true, SVGFilterElement: true, SVGForeignObjectElement: true, SVGGElement: true, SVGGeometryElement: true, SVGGraphicsElement: true, SVGImageElement: true, SVGLineElement: true, SVGLinearGradientElement: true, SVGMarkerElement: true, SVGMaskElement: true, SVGMetadataElement: true, SVGPathElement: true, SVGPatternElement: true, SVGPolygonElement: true, SVGPolylineElement: true, SVGRadialGradientElement: true, SVGRectElement: true, SVGScriptElement: true, SVGSetElement: true, SVGStopElement: true, SVGStyleElement: true, SVGElement: true, SVGSVGElement: true, SVGSwitchElement: true, SVGSymbolElement: true, SVGTSpanElement: true, SVGTextContentElement: true, SVGTextElement: true, SVGTextPathElement: true, SVGTextPositioningElement: true, SVGTitleElement: true, SVGUseElement: true, SVGViewElement: true, SVGGradientElement: true, SVGComponentTransferFunctionElement: true, SVGFEDropShadowElement: true, SVGMPathElement: true, Element: false, AbsoluteOrientationSensor: true, Accelerometer: true, AccessibleNode: true, AmbientLightSensor: true, Animation: true, ApplicationCache: true, DOMApplicationCache: true, OfflineResourceList: true, BackgroundFetchRegistration: true, BatteryManager: true, BroadcastChannel: true, CanvasCaptureMediaStreamTrack: true, DedicatedWorkerGlobalScope: true, EventSource: true, FileReader: true, FontFaceSet: true, Gyroscope: true, XMLHttpRequest: true, XMLHttpRequestEventTarget: true, XMLHttpRequestUpload: true, LinearAccelerationSensor: true, Magnetometer: true, MediaDevices: true, MediaKeySession: true, MediaQueryList: true, MediaRecorder: true, MediaSource: true, MediaStream: true, MediaStreamTrack: true, MessagePort: true, MIDIAccess: true, MIDIInput: true, MIDIOutput: true, MIDIPort: true, NetworkInformation: true, Notification: true, OffscreenCanvas: true, OrientationSensor: true, PaymentRequest: true, Performance: true, PermissionStatus: true, PresentationAvailability: true, PresentationConnection: true, PresentationConnectionList: true, PresentationRequest: true, RelativeOrientationSensor: true, RemotePlayback: true, RTCDataChannel: true, DataChannel: true, RTCDTMFSender: true, RTCPeerConnection: true, webkitRTCPeerConnection: true, mozRTCPeerConnection: true, ScreenOrientation: true, Sensor: true, ServiceWorker: true, ServiceWorkerContainer: true, ServiceWorkerGlobalScope: true, ServiceWorkerRegistration: true, SharedWorker: true, SharedWorkerGlobalScope: true, SpeechRecognition: true, SpeechSynthesis: true, SpeechSynthesisUtterance: true, VR: true, VRDevice: true, VRDisplay: true, VRSession: true, VisualViewport: true, WebSocket: true, Window: true, DOMWindow: true, Worker: true, WorkerGlobalScope: true, WorkerPerformance: true, BluetoothDevice: true, BluetoothRemoteGATTCharacteristic: true, Clipboard: true, MojoInterfaceInterceptor: true, USB: true, IDBDatabase: true, IDBOpenDBRequest: true, IDBVersionChangeRequest: true, IDBRequest: true, IDBTransaction: true, AnalyserNode: true, RealtimeAnalyserNode: true, AudioBufferSourceNode: true, AudioDestinationNode: true, AudioNode: true, AudioScheduledSourceNode: true, AudioWorkletNode: true, BiquadFilterNode: true, ChannelMergerNode: true, AudioChannelMerger: true, ChannelSplitterNode: true, AudioChannelSplitter: true, ConstantSourceNode: true, ConvolverNode: true, DelayNode: true, DynamicsCompressorNode: true, GainNode: true, AudioGainNode: true, IIRFilterNode: true, MediaElementAudioSourceNode: true, MediaStreamAudioDestinationNode: true, MediaStreamAudioSourceNode: true, OscillatorNode: true, Oscillator: true, PannerNode: true, AudioPannerNode: true, webkitAudioPannerNode: true, ScriptProcessorNode: true, JavaScriptAudioNode: true, StereoPannerNode: true, WaveShaperNode: true, EventTarget: false, File: true, FileList: true, FileWriter: true, HTMLFormElement: true, Gamepad: true, History: true, HTMLCollection: true, HTMLFormControlsCollection: true, HTMLOptionsCollection: true, Location: true, MediaList: true, MIDIInputMap: true, MIDIOutputMap: true, MimeType: true, MimeTypeArray: true, Document: true, DocumentFragment: true, HTMLDocument: true, ShadowRoot: true, XMLDocument: true, Attr: true, DocumentType: true, Node: false, NodeList: true, RadioNodeList: true, Plugin: true, PluginArray: true, RTCStatsReport: true, HTMLSelectElement: true, SourceBuffer: true, SourceBufferList: true, SpeechGrammar: true, SpeechGrammarList: true, SpeechRecognitionResult: true, Storage: true, CSSStyleSheet: true, StyleSheet: true, TextTrack: true, TextTrackCue: true, VTTCue: true, TextTrackCueList: true, TextTrackList: true, TimeRanges: true, Touch: true, TouchList: true, TrackDefaultList: true, URL: true, VideoTrackList: true, CSSRuleList: true, ClientRect: true, DOMRect: true, GamepadList: true, NamedNodeMap: true, MozNamedAttrMap: true, SpeechRecognitionResultList: true, StyleSheetList: true, SVGLength: true, SVGLengthList: true, SVGNumber: true, SVGNumberList: true, SVGPointList: true, SVGStringList: true, SVGTransform: true, SVGTransformList: true, AudioBuffer: true, AudioParamMap: true, AudioTrackList: true, AudioContext: true, webkitAudioContext: true, BaseAudioContext: false, OfflineAudioContext: true});
+    hunkHelpers.setOrUpdateInterceptorsByTag({WebGL: J.Interceptor, AbortPaymentEvent: J.JavaScriptObject, AnimationEffectReadOnly: J.JavaScriptObject, AnimationEffectTiming: J.JavaScriptObject, AnimationEffectTimingReadOnly: J.JavaScriptObject, AnimationEvent: J.JavaScriptObject, AnimationPlaybackEvent: J.JavaScriptObject, AnimationTimeline: J.JavaScriptObject, AnimationWorkletGlobalScope: J.JavaScriptObject, ApplicationCacheErrorEvent: J.JavaScriptObject, AuthenticatorAssertionResponse: J.JavaScriptObject, AuthenticatorAttestationResponse: J.JavaScriptObject, AuthenticatorResponse: J.JavaScriptObject, BackgroundFetchClickEvent: J.JavaScriptObject, BackgroundFetchEvent: J.JavaScriptObject, BackgroundFetchFailEvent: J.JavaScriptObject, BackgroundFetchFetch: J.JavaScriptObject, BackgroundFetchManager: J.JavaScriptObject, BackgroundFetchSettledFetch: J.JavaScriptObject, BackgroundFetchedEvent: J.JavaScriptObject, BarProp: J.JavaScriptObject, BarcodeDetector: J.JavaScriptObject, BeforeInstallPromptEvent: J.JavaScriptObject, BeforeUnloadEvent: J.JavaScriptObject, BlobEvent: J.JavaScriptObject, BluetoothRemoteGATTDescriptor: J.JavaScriptObject, Body: J.JavaScriptObject, BudgetState: J.JavaScriptObject, CacheStorage: J.JavaScriptObject, CanMakePaymentEvent: J.JavaScriptObject, CanvasGradient: J.JavaScriptObject, CanvasPattern: J.JavaScriptObject, CanvasRenderingContext2D: J.JavaScriptObject, Client: J.JavaScriptObject, Clients: J.JavaScriptObject, ClipboardEvent: J.JavaScriptObject, CloseEvent: J.JavaScriptObject, CompositionEvent: J.JavaScriptObject, CookieStore: J.JavaScriptObject, Coordinates: J.JavaScriptObject, Credential: J.JavaScriptObject, CredentialUserData: J.JavaScriptObject, CredentialsContainer: J.JavaScriptObject, Crypto: J.JavaScriptObject, CryptoKey: J.JavaScriptObject, CSS: J.JavaScriptObject, CSSVariableReferenceValue: J.JavaScriptObject, CustomElementRegistry: J.JavaScriptObject, CustomEvent: J.JavaScriptObject, DataTransfer: J.JavaScriptObject, DataTransferItem: J.JavaScriptObject, DeprecatedStorageInfo: J.JavaScriptObject, DeprecatedStorageQuota: J.JavaScriptObject, DeprecationReport: J.JavaScriptObject, DetectedBarcode: J.JavaScriptObject, DetectedFace: J.JavaScriptObject, DetectedText: J.JavaScriptObject, DeviceAcceleration: J.JavaScriptObject, DeviceMotionEvent: J.JavaScriptObject, DeviceOrientationEvent: J.JavaScriptObject, DeviceRotationRate: J.JavaScriptObject, DirectoryEntry: J.JavaScriptObject, webkitFileSystemDirectoryEntry: J.JavaScriptObject, FileSystemDirectoryEntry: J.JavaScriptObject, DirectoryReader: J.JavaScriptObject, WebKitDirectoryReader: J.JavaScriptObject, webkitFileSystemDirectoryReader: J.JavaScriptObject, FileSystemDirectoryReader: J.JavaScriptObject, DocumentOrShadowRoot: J.JavaScriptObject, DocumentTimeline: J.JavaScriptObject, DOMError: J.JavaScriptObject, DOMImplementation: J.JavaScriptObject, Iterator: J.JavaScriptObject, DOMMatrix: J.JavaScriptObject, DOMMatrixReadOnly: J.JavaScriptObject, DOMParser: J.JavaScriptObject, DOMPoint: J.JavaScriptObject, DOMPointReadOnly: J.JavaScriptObject, DOMQuad: J.JavaScriptObject, DOMStringMap: J.JavaScriptObject, Entry: J.JavaScriptObject, webkitFileSystemEntry: J.JavaScriptObject, FileSystemEntry: J.JavaScriptObject, ErrorEvent: J.JavaScriptObject, Event: J.JavaScriptObject, InputEvent: J.JavaScriptObject, SubmitEvent: J.JavaScriptObject, ExtendableEvent: J.JavaScriptObject, ExtendableMessageEvent: J.JavaScriptObject, External: J.JavaScriptObject, FaceDetector: J.JavaScriptObject, FederatedCredential: J.JavaScriptObject, FetchEvent: J.JavaScriptObject, FileEntry: J.JavaScriptObject, webkitFileSystemFileEntry: J.JavaScriptObject, FileSystemFileEntry: J.JavaScriptObject, DOMFileSystem: J.JavaScriptObject, WebKitFileSystem: J.JavaScriptObject, webkitFileSystem: J.JavaScriptObject, FileSystem: J.JavaScriptObject, FocusEvent: J.JavaScriptObject, FontFace: J.JavaScriptObject, FontFaceSetLoadEvent: J.JavaScriptObject, FontFaceSource: J.JavaScriptObject, ForeignFetchEvent: J.JavaScriptObject, FormData: J.JavaScriptObject, GamepadButton: J.JavaScriptObject, GamepadEvent: J.JavaScriptObject, GamepadPose: J.JavaScriptObject, Geolocation: J.JavaScriptObject, Position: J.JavaScriptObject, GeolocationPosition: J.JavaScriptObject, HashChangeEvent: J.JavaScriptObject, Headers: J.JavaScriptObject, HTMLHyperlinkElementUtils: J.JavaScriptObject, IdleDeadline: J.JavaScriptObject, ImageBitmap: J.JavaScriptObject, ImageBitmapRenderingContext: J.JavaScriptObject, ImageCapture: J.JavaScriptObject, ImageData: J.JavaScriptObject, InputDeviceCapabilities: J.JavaScriptObject, InstallEvent: J.JavaScriptObject, IntersectionObserver: J.JavaScriptObject, IntersectionObserverEntry: J.JavaScriptObject, InterventionReport: J.JavaScriptObject, KeyboardEvent: J.JavaScriptObject, KeyframeEffect: J.JavaScriptObject, KeyframeEffectReadOnly: J.JavaScriptObject, MediaCapabilities: J.JavaScriptObject, MediaCapabilitiesInfo: J.JavaScriptObject, MediaDeviceInfo: J.JavaScriptObject, MediaEncryptedEvent: J.JavaScriptObject, MediaError: J.JavaScriptObject, MediaKeyMessageEvent: J.JavaScriptObject, MediaKeyStatusMap: J.JavaScriptObject, MediaKeySystemAccess: J.JavaScriptObject, MediaKeys: J.JavaScriptObject, MediaKeysPolicy: J.JavaScriptObject, MediaMetadata: J.JavaScriptObject, MediaQueryListEvent: J.JavaScriptObject, MediaSession: J.JavaScriptObject, MediaSettingsRange: J.JavaScriptObject, MediaStreamEvent: J.JavaScriptObject, MediaStreamTrackEvent: J.JavaScriptObject, MemoryInfo: J.JavaScriptObject, MessageChannel: J.JavaScriptObject, MessageEvent: J.JavaScriptObject, Metadata: J.JavaScriptObject, MIDIConnectionEvent: J.JavaScriptObject, MIDIMessageEvent: J.JavaScriptObject, MouseEvent: J.JavaScriptObject, DragEvent: J.JavaScriptObject, MutationEvent: J.JavaScriptObject, MutationObserver: J.JavaScriptObject, WebKitMutationObserver: J.JavaScriptObject, MutationRecord: J.JavaScriptObject, NavigationPreloadManager: J.JavaScriptObject, Navigator: J.JavaScriptObject, NavigatorAutomationInformation: J.JavaScriptObject, NavigatorConcurrentHardware: J.JavaScriptObject, NavigatorCookies: J.JavaScriptObject, NavigatorUserMediaError: J.JavaScriptObject, NodeFilter: J.JavaScriptObject, NodeIterator: J.JavaScriptObject, NonDocumentTypeChildNode: J.JavaScriptObject, NonElementParentNode: J.JavaScriptObject, NoncedElement: J.JavaScriptObject, NotificationEvent: J.JavaScriptObject, OffscreenCanvasRenderingContext2D: J.JavaScriptObject, OverconstrainedError: J.JavaScriptObject, PageTransitionEvent: J.JavaScriptObject, PaintRenderingContext2D: J.JavaScriptObject, PaintSize: J.JavaScriptObject, PaintWorkletGlobalScope: J.JavaScriptObject, PasswordCredential: J.JavaScriptObject, Path2D: J.JavaScriptObject, PaymentAddress: J.JavaScriptObject, PaymentInstruments: J.JavaScriptObject, PaymentManager: J.JavaScriptObject, PaymentRequestEvent: J.JavaScriptObject, PaymentRequestUpdateEvent: J.JavaScriptObject, PaymentResponse: J.JavaScriptObject, PerformanceEntry: J.JavaScriptObject, PerformanceLongTaskTiming: J.JavaScriptObject, PerformanceMark: J.JavaScriptObject, PerformanceMeasure: J.JavaScriptObject, PerformanceNavigation: J.JavaScriptObject, PerformanceNavigationTiming: J.JavaScriptObject, PerformanceObserver: J.JavaScriptObject, PerformanceObserverEntryList: J.JavaScriptObject, PerformancePaintTiming: J.JavaScriptObject, PerformanceResourceTiming: J.JavaScriptObject, PerformanceServerTiming: J.JavaScriptObject, PerformanceTiming: J.JavaScriptObject, Permissions: J.JavaScriptObject, PhotoCapabilities: J.JavaScriptObject, PointerEvent: J.JavaScriptObject, PopStateEvent: J.JavaScriptObject, PositionError: J.JavaScriptObject, GeolocationPositionError: J.JavaScriptObject, Presentation: J.JavaScriptObject, PresentationConnectionAvailableEvent: J.JavaScriptObject, PresentationConnectionCloseEvent: J.JavaScriptObject, PresentationReceiver: J.JavaScriptObject, ProgressEvent: J.JavaScriptObject, PromiseRejectionEvent: J.JavaScriptObject, PublicKeyCredential: J.JavaScriptObject, PushEvent: J.JavaScriptObject, PushManager: J.JavaScriptObject, PushMessageData: J.JavaScriptObject, PushSubscription: J.JavaScriptObject, PushSubscriptionOptions: J.JavaScriptObject, Range: J.JavaScriptObject, RelatedApplication: J.JavaScriptObject, ReportBody: J.JavaScriptObject, ReportingObserver: J.JavaScriptObject, ResizeObserver: J.JavaScriptObject, ResizeObserverEntry: J.JavaScriptObject, RTCCertificate: J.JavaScriptObject, RTCDataChannelEvent: J.JavaScriptObject, RTCDTMFToneChangeEvent: J.JavaScriptObject, RTCIceCandidate: J.JavaScriptObject, mozRTCIceCandidate: J.JavaScriptObject, RTCLegacyStatsReport: J.JavaScriptObject, RTCPeerConnectionIceEvent: J.JavaScriptObject, RTCRtpContributingSource: J.JavaScriptObject, RTCRtpReceiver: J.JavaScriptObject, RTCRtpSender: J.JavaScriptObject, RTCSessionDescription: J.JavaScriptObject, mozRTCSessionDescription: J.JavaScriptObject, RTCStatsResponse: J.JavaScriptObject, RTCTrackEvent: J.JavaScriptObject, Screen: J.JavaScriptObject, ScrollState: J.JavaScriptObject, ScrollTimeline: J.JavaScriptObject, SecurityPolicyViolationEvent: J.JavaScriptObject, Selection: J.JavaScriptObject, SensorErrorEvent: J.JavaScriptObject, SharedArrayBuffer: J.JavaScriptObject, SpeechRecognitionAlternative: J.JavaScriptObject, SpeechRecognitionError: J.JavaScriptObject, SpeechRecognitionEvent: J.JavaScriptObject, SpeechSynthesisEvent: J.JavaScriptObject, SpeechSynthesisVoice: J.JavaScriptObject, StaticRange: J.JavaScriptObject, StorageEvent: J.JavaScriptObject, StorageManager: J.JavaScriptObject, StyleMedia: J.JavaScriptObject, StylePropertyMap: J.JavaScriptObject, StylePropertyMapReadonly: J.JavaScriptObject, SyncEvent: J.JavaScriptObject, SyncManager: J.JavaScriptObject, TaskAttributionTiming: J.JavaScriptObject, TextDetector: J.JavaScriptObject, TextEvent: J.JavaScriptObject, TextMetrics: J.JavaScriptObject, TouchEvent: J.JavaScriptObject, TrackDefault: J.JavaScriptObject, TrackEvent: J.JavaScriptObject, TransitionEvent: J.JavaScriptObject, WebKitTransitionEvent: J.JavaScriptObject, TreeWalker: J.JavaScriptObject, TrustedHTML: J.JavaScriptObject, TrustedScriptURL: J.JavaScriptObject, TrustedURL: J.JavaScriptObject, UIEvent: J.JavaScriptObject, UnderlyingSourceBase: J.JavaScriptObject, URLSearchParams: J.JavaScriptObject, VRCoordinateSystem: J.JavaScriptObject, VRDeviceEvent: J.JavaScriptObject, VRDisplayCapabilities: J.JavaScriptObject, VRDisplayEvent: J.JavaScriptObject, VREyeParameters: J.JavaScriptObject, VRFrameData: J.JavaScriptObject, VRFrameOfReference: J.JavaScriptObject, VRPose: J.JavaScriptObject, VRSessionEvent: J.JavaScriptObject, VRStageBounds: J.JavaScriptObject, VRStageBoundsPoint: J.JavaScriptObject, VRStageParameters: J.JavaScriptObject, ValidityState: J.JavaScriptObject, VideoPlaybackQuality: J.JavaScriptObject, VideoTrack: J.JavaScriptObject, VTTRegion: J.JavaScriptObject, WheelEvent: J.JavaScriptObject, WindowClient: J.JavaScriptObject, WorkletAnimation: J.JavaScriptObject, WorkletGlobalScope: J.JavaScriptObject, XPathEvaluator: J.JavaScriptObject, XPathExpression: J.JavaScriptObject, XPathNSResolver: J.JavaScriptObject, XPathResult: J.JavaScriptObject, XMLSerializer: J.JavaScriptObject, XSLTProcessor: J.JavaScriptObject, Bluetooth: J.JavaScriptObject, BluetoothCharacteristicProperties: J.JavaScriptObject, BluetoothRemoteGATTServer: J.JavaScriptObject, BluetoothRemoteGATTService: J.JavaScriptObject, BluetoothUUID: J.JavaScriptObject, BudgetService: J.JavaScriptObject, Cache: J.JavaScriptObject, DOMFileSystemSync: J.JavaScriptObject, DirectoryEntrySync: J.JavaScriptObject, DirectoryReaderSync: J.JavaScriptObject, EntrySync: J.JavaScriptObject, FileEntrySync: J.JavaScriptObject, FileReaderSync: J.JavaScriptObject, FileWriterSync: J.JavaScriptObject, HTMLAllCollection: J.JavaScriptObject, Mojo: J.JavaScriptObject, MojoHandle: J.JavaScriptObject, MojoInterfaceRequestEvent: J.JavaScriptObject, MojoWatcher: J.JavaScriptObject, NFC: J.JavaScriptObject, PagePopupController: J.JavaScriptObject, Report: J.JavaScriptObject, Request: J.JavaScriptObject, ResourceProgressEvent: J.JavaScriptObject, Response: J.JavaScriptObject, SubtleCrypto: J.JavaScriptObject, USBAlternateInterface: J.JavaScriptObject, USBConfiguration: J.JavaScriptObject, USBConnectionEvent: J.JavaScriptObject, USBDevice: J.JavaScriptObject, USBEndpoint: J.JavaScriptObject, USBInTransferResult: J.JavaScriptObject, USBInterface: J.JavaScriptObject, USBIsochronousInTransferPacket: J.JavaScriptObject, USBIsochronousInTransferResult: J.JavaScriptObject, USBIsochronousOutTransferPacket: J.JavaScriptObject, USBIsochronousOutTransferResult: J.JavaScriptObject, USBOutTransferResult: J.JavaScriptObject, WorkerLocation: J.JavaScriptObject, WorkerNavigator: J.JavaScriptObject, Worklet: J.JavaScriptObject, IDBCursor: J.JavaScriptObject, IDBCursorWithValue: J.JavaScriptObject, IDBFactory: J.JavaScriptObject, IDBIndex: J.JavaScriptObject, IDBKeyRange: J.JavaScriptObject, IDBObjectStore: J.JavaScriptObject, IDBObservation: J.JavaScriptObject, IDBObserver: J.JavaScriptObject, IDBObserverChanges: J.JavaScriptObject, IDBVersionChangeEvent: J.JavaScriptObject, SVGAngle: J.JavaScriptObject, SVGAnimatedAngle: J.JavaScriptObject, SVGAnimatedBoolean: J.JavaScriptObject, SVGAnimatedEnumeration: J.JavaScriptObject, SVGAnimatedInteger: J.JavaScriptObject, SVGAnimatedLength: J.JavaScriptObject, SVGAnimatedLengthList: J.JavaScriptObject, SVGAnimatedNumber: J.JavaScriptObject, SVGAnimatedNumberList: J.JavaScriptObject, SVGAnimatedPreserveAspectRatio: J.JavaScriptObject, SVGAnimatedRect: J.JavaScriptObject, SVGAnimatedString: J.JavaScriptObject, SVGAnimatedTransformList: J.JavaScriptObject, SVGMatrix: J.JavaScriptObject, SVGPoint: J.JavaScriptObject, SVGPreserveAspectRatio: J.JavaScriptObject, SVGRect: J.JavaScriptObject, SVGUnitTypes: J.JavaScriptObject, AudioListener: J.JavaScriptObject, AudioParam: J.JavaScriptObject, AudioProcessingEvent: J.JavaScriptObject, AudioTrack: J.JavaScriptObject, AudioWorkletGlobalScope: J.JavaScriptObject, AudioWorkletProcessor: J.JavaScriptObject, OfflineAudioCompletionEvent: J.JavaScriptObject, PeriodicWave: J.JavaScriptObject, WebGLActiveInfo: J.JavaScriptObject, ANGLEInstancedArrays: J.JavaScriptObject, ANGLE_instanced_arrays: J.JavaScriptObject, WebGLBuffer: J.JavaScriptObject, WebGLCanvas: J.JavaScriptObject, WebGLColorBufferFloat: J.JavaScriptObject, WebGLCompressedTextureASTC: J.JavaScriptObject, WebGLCompressedTextureATC: J.JavaScriptObject, WEBGL_compressed_texture_atc: J.JavaScriptObject, WebGLCompressedTextureETC1: J.JavaScriptObject, WEBGL_compressed_texture_etc1: J.JavaScriptObject, WebGLCompressedTextureETC: J.JavaScriptObject, WebGLCompressedTexturePVRTC: J.JavaScriptObject, WEBGL_compressed_texture_pvrtc: J.JavaScriptObject, WebGLCompressedTextureS3TC: J.JavaScriptObject, WEBGL_compressed_texture_s3tc: J.JavaScriptObject, WebGLCompressedTextureS3TCsRGB: J.JavaScriptObject, WebGLContextEvent: J.JavaScriptObject, WebGLDebugRendererInfo: J.JavaScriptObject, WEBGL_debug_renderer_info: J.JavaScriptObject, WebGLDebugShaders: J.JavaScriptObject, WEBGL_debug_shaders: J.JavaScriptObject, WebGLDepthTexture: J.JavaScriptObject, WEBGL_depth_texture: J.JavaScriptObject, WebGLDrawBuffers: J.JavaScriptObject, WEBGL_draw_buffers: J.JavaScriptObject, EXTsRGB: J.JavaScriptObject, EXT_sRGB: J.JavaScriptObject, EXTBlendMinMax: J.JavaScriptObject, EXT_blend_minmax: J.JavaScriptObject, EXTColorBufferFloat: J.JavaScriptObject, EXTColorBufferHalfFloat: J.JavaScriptObject, EXTDisjointTimerQuery: J.JavaScriptObject, EXTDisjointTimerQueryWebGL2: J.JavaScriptObject, EXTFragDepth: J.JavaScriptObject, EXT_frag_depth: J.JavaScriptObject, EXTShaderTextureLOD: J.JavaScriptObject, EXT_shader_texture_lod: J.JavaScriptObject, EXTTextureFilterAnisotropic: J.JavaScriptObject, EXT_texture_filter_anisotropic: J.JavaScriptObject, WebGLFramebuffer: J.JavaScriptObject, WebGLGetBufferSubDataAsync: J.JavaScriptObject, WebGLLoseContext: J.JavaScriptObject, WebGLExtensionLoseContext: J.JavaScriptObject, WEBGL_lose_context: J.JavaScriptObject, OESElementIndexUint: J.JavaScriptObject, OES_element_index_uint: J.JavaScriptObject, OESStandardDerivatives: J.JavaScriptObject, OES_standard_derivatives: J.JavaScriptObject, OESTextureFloat: J.JavaScriptObject, OES_texture_float: J.JavaScriptObject, OESTextureFloatLinear: J.JavaScriptObject, OES_texture_float_linear: J.JavaScriptObject, OESTextureHalfFloat: J.JavaScriptObject, OES_texture_half_float: J.JavaScriptObject, OESTextureHalfFloatLinear: J.JavaScriptObject, OES_texture_half_float_linear: J.JavaScriptObject, OESVertexArrayObject: J.JavaScriptObject, OES_vertex_array_object: J.JavaScriptObject, WebGLProgram: J.JavaScriptObject, WebGLQuery: J.JavaScriptObject, WebGLRenderbuffer: J.JavaScriptObject, WebGLRenderingContext: J.JavaScriptObject, WebGL2RenderingContext: J.JavaScriptObject, WebGLSampler: J.JavaScriptObject, WebGLShader: J.JavaScriptObject, WebGLShaderPrecisionFormat: J.JavaScriptObject, WebGLSync: J.JavaScriptObject, WebGLTexture: J.JavaScriptObject, WebGLTimerQueryEXT: J.JavaScriptObject, WebGLTransformFeedback: J.JavaScriptObject, WebGLUniformLocation: J.JavaScriptObject, WebGLVertexArrayObject: J.JavaScriptObject, WebGLVertexArrayObjectOES: J.JavaScriptObject, WebGL2RenderingContextBase: J.JavaScriptObject, ArrayBuffer: A.NativeByteBuffer, ArrayBufferView: A.NativeTypedData, DataView: A.NativeByteData, Float32Array: A.NativeFloat32List, Float64Array: A.NativeFloat64List, Int16Array: A.NativeInt16List, Int32Array: A.NativeInt32List, Int8Array: A.NativeInt8List, Uint16Array: A.NativeUint16List, Uint32Array: A.NativeUint32List, Uint8ClampedArray: A.NativeUint8ClampedList, CanvasPixelArray: A.NativeUint8ClampedList, Uint8Array: A.NativeUint8List, HTMLAudioElement: A.HtmlElement, HTMLBRElement: A.HtmlElement, HTMLBaseElement: A.HtmlElement, HTMLBodyElement: A.HtmlElement, HTMLButtonElement: A.HtmlElement, HTMLCanvasElement: A.HtmlElement, HTMLContentElement: A.HtmlElement, HTMLDListElement: A.HtmlElement, HTMLDataElement: A.HtmlElement, HTMLDataListElement: A.HtmlElement, HTMLDetailsElement: A.HtmlElement, HTMLDialogElement: A.HtmlElement, HTMLDivElement: A.HtmlElement, HTMLEmbedElement: A.HtmlElement, HTMLFieldSetElement: A.HtmlElement, HTMLHRElement: A.HtmlElement, HTMLHeadElement: A.HtmlElement, HTMLHeadingElement: A.HtmlElement, HTMLHtmlElement: A.HtmlElement, HTMLIFrameElement: A.HtmlElement, HTMLImageElement: A.HtmlElement, HTMLInputElement: A.HtmlElement, HTMLLIElement: A.HtmlElement, HTMLLabelElement: A.HtmlElement, HTMLLegendElement: A.HtmlElement, HTMLLinkElement: A.HtmlElement, HTMLMapElement: A.HtmlElement, HTMLMediaElement: A.HtmlElement, HTMLMenuElement: A.HtmlElement, HTMLMetaElement: A.HtmlElement, HTMLMeterElement: A.HtmlElement, HTMLModElement: A.HtmlElement, HTMLOListElement: A.HtmlElement, HTMLObjectElement: A.HtmlElement, HTMLOptGroupElement: A.HtmlElement, HTMLOptionElement: A.HtmlElement, HTMLOutputElement: A.HtmlElement, HTMLParagraphElement: A.HtmlElement, HTMLParamElement: A.HtmlElement, HTMLPictureElement: A.HtmlElement, HTMLPreElement: A.HtmlElement, HTMLProgressElement: A.HtmlElement, HTMLQuoteElement: A.HtmlElement, HTMLScriptElement: A.HtmlElement, HTMLShadowElement: A.HtmlElement, HTMLSlotElement: A.HtmlElement, HTMLSourceElement: A.HtmlElement, HTMLSpanElement: A.HtmlElement, HTMLStyleElement: A.HtmlElement, HTMLTableCaptionElement: A.HtmlElement, HTMLTableCellElement: A.HtmlElement, HTMLTableDataCellElement: A.HtmlElement, HTMLTableHeaderCellElement: A.HtmlElement, HTMLTableColElement: A.HtmlElement, HTMLTableElement: A.HtmlElement, HTMLTableRowElement: A.HtmlElement, HTMLTableSectionElement: A.HtmlElement, HTMLTemplateElement: A.HtmlElement, HTMLTextAreaElement: A.HtmlElement, HTMLTimeElement: A.HtmlElement, HTMLTitleElement: A.HtmlElement, HTMLTrackElement: A.HtmlElement, HTMLUListElement: A.HtmlElement, HTMLUnknownElement: A.HtmlElement, HTMLVideoElement: A.HtmlElement, HTMLDirectoryElement: A.HtmlElement, HTMLFontElement: A.HtmlElement, HTMLFrameElement: A.HtmlElement, HTMLFrameSetElement: A.HtmlElement, HTMLMarqueeElement: A.HtmlElement, HTMLElement: A.HtmlElement, AccessibleNodeList: A.AccessibleNodeList, HTMLAnchorElement: A.AnchorElement, HTMLAreaElement: A.AreaElement, Blob: A.Blob, CDATASection: A.CharacterData, CharacterData: A.CharacterData, Comment: A.CharacterData, ProcessingInstruction: A.CharacterData, Text: A.CharacterData, CSSPerspective: A.CssPerspective, CSSCharsetRule: A.CssRule, CSSConditionRule: A.CssRule, CSSFontFaceRule: A.CssRule, CSSGroupingRule: A.CssRule, CSSImportRule: A.CssRule, CSSKeyframeRule: A.CssRule, MozCSSKeyframeRule: A.CssRule, WebKitCSSKeyframeRule: A.CssRule, CSSKeyframesRule: A.CssRule, MozCSSKeyframesRule: A.CssRule, WebKitCSSKeyframesRule: A.CssRule, CSSMediaRule: A.CssRule, CSSNamespaceRule: A.CssRule, CSSPageRule: A.CssRule, CSSRule: A.CssRule, CSSStyleRule: A.CssRule, CSSSupportsRule: A.CssRule, CSSViewportRule: A.CssRule, CSSStyleDeclaration: A.CssStyleDeclaration, MSStyleCSSProperties: A.CssStyleDeclaration, CSS2Properties: A.CssStyleDeclaration, CSSImageValue: A.CssStyleValue, CSSKeywordValue: A.CssStyleValue, CSSNumericValue: A.CssStyleValue, CSSPositionValue: A.CssStyleValue, CSSResourceValue: A.CssStyleValue, CSSUnitValue: A.CssStyleValue, CSSURLImageValue: A.CssStyleValue, CSSStyleValue: A.CssStyleValue, CSSMatrixComponent: A.CssTransformComponent, CSSRotation: A.CssTransformComponent, CSSScale: A.CssTransformComponent, CSSSkew: A.CssTransformComponent, CSSTranslation: A.CssTransformComponent, CSSTransformComponent: A.CssTransformComponent, CSSTransformValue: A.CssTransformValue, CSSUnparsedValue: A.CssUnparsedValue, DataTransferItemList: A.DataTransferItemList, DOMException: A.DomException, ClientRectList: A.DomRectList, DOMRectList: A.DomRectList, DOMRectReadOnly: A.DomRectReadOnly, DOMStringList: A.DomStringList, DOMTokenList: A.DomTokenList, MathMLElement: A.Element, SVGAElement: A.Element, SVGAnimateElement: A.Element, SVGAnimateMotionElement: A.Element, SVGAnimateTransformElement: A.Element, SVGAnimationElement: A.Element, SVGCircleElement: A.Element, SVGClipPathElement: A.Element, SVGDefsElement: A.Element, SVGDescElement: A.Element, SVGDiscardElement: A.Element, SVGEllipseElement: A.Element, SVGFEBlendElement: A.Element, SVGFEColorMatrixElement: A.Element, SVGFEComponentTransferElement: A.Element, SVGFECompositeElement: A.Element, SVGFEConvolveMatrixElement: A.Element, SVGFEDiffuseLightingElement: A.Element, SVGFEDisplacementMapElement: A.Element, SVGFEDistantLightElement: A.Element, SVGFEFloodElement: A.Element, SVGFEFuncAElement: A.Element, SVGFEFuncBElement: A.Element, SVGFEFuncGElement: A.Element, SVGFEFuncRElement: A.Element, SVGFEGaussianBlurElement: A.Element, SVGFEImageElement: A.Element, SVGFEMergeElement: A.Element, SVGFEMergeNodeElement: A.Element, SVGFEMorphologyElement: A.Element, SVGFEOffsetElement: A.Element, SVGFEPointLightElement: A.Element, SVGFESpecularLightingElement: A.Element, SVGFESpotLightElement: A.Element, SVGFETileElement: A.Element, SVGFETurbulenceElement: A.Element, SVGFilterElement: A.Element, SVGForeignObjectElement: A.Element, SVGGElement: A.Element, SVGGeometryElement: A.Element, SVGGraphicsElement: A.Element, SVGImageElement: A.Element, SVGLineElement: A.Element, SVGLinearGradientElement: A.Element, SVGMarkerElement: A.Element, SVGMaskElement: A.Element, SVGMetadataElement: A.Element, SVGPathElement: A.Element, SVGPatternElement: A.Element, SVGPolygonElement: A.Element, SVGPolylineElement: A.Element, SVGRadialGradientElement: A.Element, SVGRectElement: A.Element, SVGScriptElement: A.Element, SVGSetElement: A.Element, SVGStopElement: A.Element, SVGStyleElement: A.Element, SVGElement: A.Element, SVGSVGElement: A.Element, SVGSwitchElement: A.Element, SVGSymbolElement: A.Element, SVGTSpanElement: A.Element, SVGTextContentElement: A.Element, SVGTextElement: A.Element, SVGTextPathElement: A.Element, SVGTextPositioningElement: A.Element, SVGTitleElement: A.Element, SVGUseElement: A.Element, SVGViewElement: A.Element, SVGGradientElement: A.Element, SVGComponentTransferFunctionElement: A.Element, SVGFEDropShadowElement: A.Element, SVGMPathElement: A.Element, Element: A.Element, AbsoluteOrientationSensor: A.EventTarget, Accelerometer: A.EventTarget, AccessibleNode: A.EventTarget, AmbientLightSensor: A.EventTarget, Animation: A.EventTarget, ApplicationCache: A.EventTarget, DOMApplicationCache: A.EventTarget, OfflineResourceList: A.EventTarget, BackgroundFetchRegistration: A.EventTarget, BatteryManager: A.EventTarget, BroadcastChannel: A.EventTarget, CanvasCaptureMediaStreamTrack: A.EventTarget, DedicatedWorkerGlobalScope: A.EventTarget, EventSource: A.EventTarget, FileReader: A.EventTarget, FontFaceSet: A.EventTarget, Gyroscope: A.EventTarget, XMLHttpRequest: A.EventTarget, XMLHttpRequestEventTarget: A.EventTarget, XMLHttpRequestUpload: A.EventTarget, LinearAccelerationSensor: A.EventTarget, Magnetometer: A.EventTarget, MediaDevices: A.EventTarget, MediaKeySession: A.EventTarget, MediaQueryList: A.EventTarget, MediaRecorder: A.EventTarget, MediaSource: A.EventTarget, MediaStream: A.EventTarget, MediaStreamTrack: A.EventTarget, MessagePort: A.EventTarget, MIDIAccess: A.EventTarget, MIDIInput: A.EventTarget, MIDIOutput: A.EventTarget, MIDIPort: A.EventTarget, NetworkInformation: A.EventTarget, Notification: A.EventTarget, OffscreenCanvas: A.EventTarget, OrientationSensor: A.EventTarget, PaymentRequest: A.EventTarget, Performance: A.EventTarget, PermissionStatus: A.EventTarget, PresentationAvailability: A.EventTarget, PresentationConnection: A.EventTarget, PresentationConnectionList: A.EventTarget, PresentationRequest: A.EventTarget, RelativeOrientationSensor: A.EventTarget, RemotePlayback: A.EventTarget, RTCDataChannel: A.EventTarget, DataChannel: A.EventTarget, RTCDTMFSender: A.EventTarget, RTCPeerConnection: A.EventTarget, webkitRTCPeerConnection: A.EventTarget, mozRTCPeerConnection: A.EventTarget, ScreenOrientation: A.EventTarget, Sensor: A.EventTarget, ServiceWorker: A.EventTarget, ServiceWorkerContainer: A.EventTarget, ServiceWorkerGlobalScope: A.EventTarget, ServiceWorkerRegistration: A.EventTarget, SharedWorker: A.EventTarget, SharedWorkerGlobalScope: A.EventTarget, SpeechRecognition: A.EventTarget, webkitSpeechRecognition: A.EventTarget, SpeechSynthesis: A.EventTarget, SpeechSynthesisUtterance: A.EventTarget, VR: A.EventTarget, VRDevice: A.EventTarget, VRDisplay: A.EventTarget, VRSession: A.EventTarget, VisualViewport: A.EventTarget, WebSocket: A.EventTarget, Window: A.EventTarget, DOMWindow: A.EventTarget, Worker: A.EventTarget, WorkerGlobalScope: A.EventTarget, WorkerPerformance: A.EventTarget, BluetoothDevice: A.EventTarget, BluetoothRemoteGATTCharacteristic: A.EventTarget, Clipboard: A.EventTarget, MojoInterfaceInterceptor: A.EventTarget, USB: A.EventTarget, IDBDatabase: A.EventTarget, IDBOpenDBRequest: A.EventTarget, IDBVersionChangeRequest: A.EventTarget, IDBRequest: A.EventTarget, IDBTransaction: A.EventTarget, AnalyserNode: A.EventTarget, RealtimeAnalyserNode: A.EventTarget, AudioBufferSourceNode: A.EventTarget, AudioDestinationNode: A.EventTarget, AudioNode: A.EventTarget, AudioScheduledSourceNode: A.EventTarget, AudioWorkletNode: A.EventTarget, BiquadFilterNode: A.EventTarget, ChannelMergerNode: A.EventTarget, AudioChannelMerger: A.EventTarget, ChannelSplitterNode: A.EventTarget, AudioChannelSplitter: A.EventTarget, ConstantSourceNode: A.EventTarget, ConvolverNode: A.EventTarget, DelayNode: A.EventTarget, DynamicsCompressorNode: A.EventTarget, GainNode: A.EventTarget, AudioGainNode: A.EventTarget, IIRFilterNode: A.EventTarget, MediaElementAudioSourceNode: A.EventTarget, MediaStreamAudioDestinationNode: A.EventTarget, MediaStreamAudioSourceNode: A.EventTarget, OscillatorNode: A.EventTarget, Oscillator: A.EventTarget, PannerNode: A.EventTarget, AudioPannerNode: A.EventTarget, webkitAudioPannerNode: A.EventTarget, ScriptProcessorNode: A.EventTarget, JavaScriptAudioNode: A.EventTarget, StereoPannerNode: A.EventTarget, WaveShaperNode: A.EventTarget, EventTarget: A.EventTarget, File: A.File, FileList: A.FileList, FileWriter: A.FileWriter, HTMLFormElement: A.FormElement, Gamepad: A.Gamepad, History: A.History, HTMLCollection: A.HtmlCollection, HTMLFormControlsCollection: A.HtmlCollection, HTMLOptionsCollection: A.HtmlCollection, Location: A.Location, MediaList: A.MediaList, MIDIInputMap: A.MidiInputMap, MIDIOutputMap: A.MidiOutputMap, MimeType: A.MimeType, MimeTypeArray: A.MimeTypeArray, Document: A.Node, DocumentFragment: A.Node, HTMLDocument: A.Node, ShadowRoot: A.Node, XMLDocument: A.Node, Attr: A.Node, DocumentType: A.Node, Node: A.Node, NodeList: A.NodeList, RadioNodeList: A.NodeList, Plugin: A.Plugin, PluginArray: A.PluginArray, RTCStatsReport: A.RtcStatsReport, HTMLSelectElement: A.SelectElement, SourceBuffer: A.SourceBuffer, SourceBufferList: A.SourceBufferList, SpeechGrammar: A.SpeechGrammar, SpeechGrammarList: A.SpeechGrammarList, SpeechRecognitionResult: A.SpeechRecognitionResult, Storage: A.Storage, CSSStyleSheet: A.StyleSheet, StyleSheet: A.StyleSheet, TextTrack: A.TextTrack, TextTrackCue: A.TextTrackCue, VTTCue: A.TextTrackCue, TextTrackCueList: A.TextTrackCueList, TextTrackList: A.TextTrackList, TimeRanges: A.TimeRanges, Touch: A.Touch, TouchList: A.TouchList, TrackDefaultList: A.TrackDefaultList, URL: A.Url, VideoTrackList: A.VideoTrackList, CSSRuleList: A._CssRuleList, ClientRect: A._DomRect, DOMRect: A._DomRect, GamepadList: A._GamepadList, NamedNodeMap: A._NamedNodeMap, MozNamedAttrMap: A._NamedNodeMap, SpeechRecognitionResultList: A._SpeechRecognitionResultList, StyleSheetList: A._StyleSheetList, SVGLength: A.Length, SVGLengthList: A.LengthList, SVGNumber: A.Number, SVGNumberList: A.NumberList, SVGPointList: A.PointList, SVGStringList: A.StringList, SVGTransform: A.Transform, SVGTransformList: A.TransformList, AudioBuffer: A.AudioBuffer, AudioParamMap: A.AudioParamMap, AudioTrackList: A.AudioTrackList, AudioContext: A.BaseAudioContext, webkitAudioContext: A.BaseAudioContext, BaseAudioContext: A.BaseAudioContext, OfflineAudioContext: A.OfflineAudioContext});
+    hunkHelpers.setOrUpdateLeafTags({WebGL: true, AbortPaymentEvent: true, AnimationEffectReadOnly: true, AnimationEffectTiming: true, AnimationEffectTimingReadOnly: true, AnimationEvent: true, AnimationPlaybackEvent: true, AnimationTimeline: true, AnimationWorkletGlobalScope: true, ApplicationCacheErrorEvent: true, AuthenticatorAssertionResponse: true, AuthenticatorAttestationResponse: true, AuthenticatorResponse: true, BackgroundFetchClickEvent: true, BackgroundFetchEvent: true, BackgroundFetchFailEvent: true, BackgroundFetchFetch: true, BackgroundFetchManager: true, BackgroundFetchSettledFetch: true, BackgroundFetchedEvent: true, BarProp: true, BarcodeDetector: true, BeforeInstallPromptEvent: true, BeforeUnloadEvent: true, BlobEvent: true, BluetoothRemoteGATTDescriptor: true, Body: true, BudgetState: true, CacheStorage: true, CanMakePaymentEvent: true, CanvasGradient: true, CanvasPattern: true, CanvasRenderingContext2D: true, Client: true, Clients: true, ClipboardEvent: true, CloseEvent: true, CompositionEvent: true, CookieStore: true, Coordinates: true, Credential: true, CredentialUserData: true, CredentialsContainer: true, Crypto: true, CryptoKey: true, CSS: true, CSSVariableReferenceValue: true, CustomElementRegistry: true, CustomEvent: true, DataTransfer: true, DataTransferItem: true, DeprecatedStorageInfo: true, DeprecatedStorageQuota: true, DeprecationReport: true, DetectedBarcode: true, DetectedFace: true, DetectedText: true, DeviceAcceleration: true, DeviceMotionEvent: true, DeviceOrientationEvent: true, DeviceRotationRate: true, DirectoryEntry: true, webkitFileSystemDirectoryEntry: true, FileSystemDirectoryEntry: true, DirectoryReader: true, WebKitDirectoryReader: true, webkitFileSystemDirectoryReader: true, FileSystemDirectoryReader: true, DocumentOrShadowRoot: true, DocumentTimeline: true, DOMError: true, DOMImplementation: true, Iterator: true, DOMMatrix: true, DOMMatrixReadOnly: true, DOMParser: true, DOMPoint: true, DOMPointReadOnly: true, DOMQuad: true, DOMStringMap: true, Entry: true, webkitFileSystemEntry: true, FileSystemEntry: true, ErrorEvent: true, Event: true, InputEvent: true, SubmitEvent: true, ExtendableEvent: true, ExtendableMessageEvent: true, External: true, FaceDetector: true, FederatedCredential: true, FetchEvent: true, FileEntry: true, webkitFileSystemFileEntry: true, FileSystemFileEntry: true, DOMFileSystem: true, WebKitFileSystem: true, webkitFileSystem: true, FileSystem: true, FocusEvent: true, FontFace: true, FontFaceSetLoadEvent: true, FontFaceSource: true, ForeignFetchEvent: true, FormData: true, GamepadButton: true, GamepadEvent: true, GamepadPose: true, Geolocation: true, Position: true, GeolocationPosition: true, HashChangeEvent: true, Headers: true, HTMLHyperlinkElementUtils: true, IdleDeadline: true, ImageBitmap: true, ImageBitmapRenderingContext: true, ImageCapture: true, ImageData: true, InputDeviceCapabilities: true, InstallEvent: true, IntersectionObserver: true, IntersectionObserverEntry: true, InterventionReport: true, KeyboardEvent: true, KeyframeEffect: true, KeyframeEffectReadOnly: true, MediaCapabilities: true, MediaCapabilitiesInfo: true, MediaDeviceInfo: true, MediaEncryptedEvent: true, MediaError: true, MediaKeyMessageEvent: true, MediaKeyStatusMap: true, MediaKeySystemAccess: true, MediaKeys: true, MediaKeysPolicy: true, MediaMetadata: true, MediaQueryListEvent: true, MediaSession: true, MediaSettingsRange: true, MediaStreamEvent: true, MediaStreamTrackEvent: true, MemoryInfo: true, MessageChannel: true, MessageEvent: true, Metadata: true, MIDIConnectionEvent: true, MIDIMessageEvent: true, MouseEvent: true, DragEvent: true, MutationEvent: true, MutationObserver: true, WebKitMutationObserver: true, MutationRecord: true, NavigationPreloadManager: true, Navigator: true, NavigatorAutomationInformation: true, NavigatorConcurrentHardware: true, NavigatorCookies: true, NavigatorUserMediaError: true, NodeFilter: true, NodeIterator: true, NonDocumentTypeChildNode: true, NonElementParentNode: true, NoncedElement: true, NotificationEvent: true, OffscreenCanvasRenderingContext2D: true, OverconstrainedError: true, PageTransitionEvent: true, PaintRenderingContext2D: true, PaintSize: true, PaintWorkletGlobalScope: true, PasswordCredential: true, Path2D: true, PaymentAddress: true, PaymentInstruments: true, PaymentManager: true, PaymentRequestEvent: true, PaymentRequestUpdateEvent: true, PaymentResponse: true, PerformanceEntry: true, PerformanceLongTaskTiming: true, PerformanceMark: true, PerformanceMeasure: true, PerformanceNavigation: true, PerformanceNavigationTiming: true, PerformanceObserver: true, PerformanceObserverEntryList: true, PerformancePaintTiming: true, PerformanceResourceTiming: true, PerformanceServerTiming: true, PerformanceTiming: true, Permissions: true, PhotoCapabilities: true, PointerEvent: true, PopStateEvent: true, PositionError: true, GeolocationPositionError: true, Presentation: true, PresentationConnectionAvailableEvent: true, PresentationConnectionCloseEvent: true, PresentationReceiver: true, ProgressEvent: true, PromiseRejectionEvent: true, PublicKeyCredential: true, PushEvent: true, PushManager: true, PushMessageData: true, PushSubscription: true, PushSubscriptionOptions: true, Range: true, RelatedApplication: true, ReportBody: true, ReportingObserver: true, ResizeObserver: true, ResizeObserverEntry: true, RTCCertificate: true, RTCDataChannelEvent: true, RTCDTMFToneChangeEvent: true, RTCIceCandidate: true, mozRTCIceCandidate: true, RTCLegacyStatsReport: true, RTCPeerConnectionIceEvent: true, RTCRtpContributingSource: true, RTCRtpReceiver: true, RTCRtpSender: true, RTCSessionDescription: true, mozRTCSessionDescription: true, RTCStatsResponse: true, RTCTrackEvent: true, Screen: true, ScrollState: true, ScrollTimeline: true, SecurityPolicyViolationEvent: true, Selection: true, SensorErrorEvent: true, SharedArrayBuffer: true, SpeechRecognitionAlternative: true, SpeechRecognitionError: true, SpeechRecognitionEvent: true, SpeechSynthesisEvent: true, SpeechSynthesisVoice: true, StaticRange: true, StorageEvent: true, StorageManager: true, StyleMedia: true, StylePropertyMap: true, StylePropertyMapReadonly: true, SyncEvent: true, SyncManager: true, TaskAttributionTiming: true, TextDetector: true, TextEvent: true, TextMetrics: true, TouchEvent: true, TrackDefault: true, TrackEvent: true, TransitionEvent: true, WebKitTransitionEvent: true, TreeWalker: true, TrustedHTML: true, TrustedScriptURL: true, TrustedURL: true, UIEvent: true, UnderlyingSourceBase: true, URLSearchParams: true, VRCoordinateSystem: true, VRDeviceEvent: true, VRDisplayCapabilities: true, VRDisplayEvent: true, VREyeParameters: true, VRFrameData: true, VRFrameOfReference: true, VRPose: true, VRSessionEvent: true, VRStageBounds: true, VRStageBoundsPoint: true, VRStageParameters: true, ValidityState: true, VideoPlaybackQuality: true, VideoTrack: true, VTTRegion: true, WheelEvent: true, WindowClient: true, WorkletAnimation: true, WorkletGlobalScope: true, XPathEvaluator: true, XPathExpression: true, XPathNSResolver: true, XPathResult: true, XMLSerializer: true, XSLTProcessor: true, Bluetooth: true, BluetoothCharacteristicProperties: true, BluetoothRemoteGATTServer: true, BluetoothRemoteGATTService: true, BluetoothUUID: true, BudgetService: true, Cache: true, DOMFileSystemSync: true, DirectoryEntrySync: true, DirectoryReaderSync: true, EntrySync: true, FileEntrySync: true, FileReaderSync: true, FileWriterSync: true, HTMLAllCollection: true, Mojo: true, MojoHandle: true, MojoInterfaceRequestEvent: true, MojoWatcher: true, NFC: true, PagePopupController: true, Report: true, Request: true, ResourceProgressEvent: true, Response: true, SubtleCrypto: true, USBAlternateInterface: true, USBConfiguration: true, USBConnectionEvent: true, USBDevice: true, USBEndpoint: true, USBInTransferResult: true, USBInterface: true, USBIsochronousInTransferPacket: true, USBIsochronousInTransferResult: true, USBIsochronousOutTransferPacket: true, USBIsochronousOutTransferResult: true, USBOutTransferResult: true, WorkerLocation: true, WorkerNavigator: true, Worklet: true, IDBCursor: true, IDBCursorWithValue: true, IDBFactory: true, IDBIndex: true, IDBKeyRange: true, IDBObjectStore: true, IDBObservation: true, IDBObserver: true, IDBObserverChanges: true, IDBVersionChangeEvent: true, SVGAngle: true, SVGAnimatedAngle: true, SVGAnimatedBoolean: true, SVGAnimatedEnumeration: true, SVGAnimatedInteger: true, SVGAnimatedLength: true, SVGAnimatedLengthList: true, SVGAnimatedNumber: true, SVGAnimatedNumberList: true, SVGAnimatedPreserveAspectRatio: true, SVGAnimatedRect: true, SVGAnimatedString: true, SVGAnimatedTransformList: true, SVGMatrix: true, SVGPoint: true, SVGPreserveAspectRatio: true, SVGRect: true, SVGUnitTypes: true, AudioListener: true, AudioParam: true, AudioProcessingEvent: true, AudioTrack: true, AudioWorkletGlobalScope: true, AudioWorkletProcessor: true, OfflineAudioCompletionEvent: true, PeriodicWave: true, WebGLActiveInfo: true, ANGLEInstancedArrays: true, ANGLE_instanced_arrays: true, WebGLBuffer: true, WebGLCanvas: true, WebGLColorBufferFloat: true, WebGLCompressedTextureASTC: true, WebGLCompressedTextureATC: true, WEBGL_compressed_texture_atc: true, WebGLCompressedTextureETC1: true, WEBGL_compressed_texture_etc1: true, WebGLCompressedTextureETC: true, WebGLCompressedTexturePVRTC: true, WEBGL_compressed_texture_pvrtc: true, WebGLCompressedTextureS3TC: true, WEBGL_compressed_texture_s3tc: true, WebGLCompressedTextureS3TCsRGB: true, WebGLContextEvent: true, WebGLDebugRendererInfo: true, WEBGL_debug_renderer_info: true, WebGLDebugShaders: true, WEBGL_debug_shaders: true, WebGLDepthTexture: true, WEBGL_depth_texture: true, WebGLDrawBuffers: true, WEBGL_draw_buffers: true, EXTsRGB: true, EXT_sRGB: true, EXTBlendMinMax: true, EXT_blend_minmax: true, EXTColorBufferFloat: true, EXTColorBufferHalfFloat: true, EXTDisjointTimerQuery: true, EXTDisjointTimerQueryWebGL2: true, EXTFragDepth: true, EXT_frag_depth: true, EXTShaderTextureLOD: true, EXT_shader_texture_lod: true, EXTTextureFilterAnisotropic: true, EXT_texture_filter_anisotropic: true, WebGLFramebuffer: true, WebGLGetBufferSubDataAsync: true, WebGLLoseContext: true, WebGLExtensionLoseContext: true, WEBGL_lose_context: true, OESElementIndexUint: true, OES_element_index_uint: true, OESStandardDerivatives: true, OES_standard_derivatives: true, OESTextureFloat: true, OES_texture_float: true, OESTextureFloatLinear: true, OES_texture_float_linear: true, OESTextureHalfFloat: true, OES_texture_half_float: true, OESTextureHalfFloatLinear: true, OES_texture_half_float_linear: true, OESVertexArrayObject: true, OES_vertex_array_object: true, WebGLProgram: true, WebGLQuery: true, WebGLRenderbuffer: true, WebGLRenderingContext: true, WebGL2RenderingContext: true, WebGLSampler: true, WebGLShader: true, WebGLShaderPrecisionFormat: true, WebGLSync: true, WebGLTexture: true, WebGLTimerQueryEXT: true, WebGLTransformFeedback: true, WebGLUniformLocation: true, WebGLVertexArrayObject: true, WebGLVertexArrayObjectOES: true, WebGL2RenderingContextBase: true, ArrayBuffer: true, ArrayBufferView: false, DataView: true, Float32Array: true, Float64Array: true, Int16Array: true, Int32Array: true, Int8Array: true, Uint16Array: true, Uint32Array: true, Uint8ClampedArray: true, CanvasPixelArray: true, Uint8Array: false, HTMLAudioElement: true, HTMLBRElement: true, HTMLBaseElement: true, HTMLBodyElement: true, HTMLButtonElement: true, HTMLCanvasElement: true, HTMLContentElement: true, HTMLDListElement: true, HTMLDataElement: true, HTMLDataListElement: true, HTMLDetailsElement: true, HTMLDialogElement: true, HTMLDivElement: true, HTMLEmbedElement: true, HTMLFieldSetElement: true, HTMLHRElement: true, HTMLHeadElement: true, HTMLHeadingElement: true, HTMLHtmlElement: true, HTMLIFrameElement: true, HTMLImageElement: true, HTMLInputElement: true, HTMLLIElement: true, HTMLLabelElement: true, HTMLLegendElement: true, HTMLLinkElement: true, HTMLMapElement: true, HTMLMediaElement: true, HTMLMenuElement: true, HTMLMetaElement: true, HTMLMeterElement: true, HTMLModElement: true, HTMLOListElement: true, HTMLObjectElement: true, HTMLOptGroupElement: true, HTMLOptionElement: true, HTMLOutputElement: true, HTMLParagraphElement: true, HTMLParamElement: true, HTMLPictureElement: true, HTMLPreElement: true, HTMLProgressElement: true, HTMLQuoteElement: true, HTMLScriptElement: true, HTMLShadowElement: true, HTMLSlotElement: true, HTMLSourceElement: true, HTMLSpanElement: true, HTMLStyleElement: true, HTMLTableCaptionElement: true, HTMLTableCellElement: true, HTMLTableDataCellElement: true, HTMLTableHeaderCellElement: true, HTMLTableColElement: true, HTMLTableElement: true, HTMLTableRowElement: true, HTMLTableSectionElement: true, HTMLTemplateElement: true, HTMLTextAreaElement: true, HTMLTimeElement: true, HTMLTitleElement: true, HTMLTrackElement: true, HTMLUListElement: true, HTMLUnknownElement: true, HTMLVideoElement: true, HTMLDirectoryElement: true, HTMLFontElement: true, HTMLFrameElement: true, HTMLFrameSetElement: true, HTMLMarqueeElement: true, HTMLElement: false, AccessibleNodeList: true, HTMLAnchorElement: true, HTMLAreaElement: true, Blob: false, CDATASection: true, CharacterData: true, Comment: true, ProcessingInstruction: true, Text: true, CSSPerspective: true, CSSCharsetRule: true, CSSConditionRule: true, CSSFontFaceRule: true, CSSGroupingRule: true, CSSImportRule: true, CSSKeyframeRule: true, MozCSSKeyframeRule: true, WebKitCSSKeyframeRule: true, CSSKeyframesRule: true, MozCSSKeyframesRule: true, WebKitCSSKeyframesRule: true, CSSMediaRule: true, CSSNamespaceRule: true, CSSPageRule: true, CSSRule: true, CSSStyleRule: true, CSSSupportsRule: true, CSSViewportRule: true, CSSStyleDeclaration: true, MSStyleCSSProperties: true, CSS2Properties: true, CSSImageValue: true, CSSKeywordValue: true, CSSNumericValue: true, CSSPositionValue: true, CSSResourceValue: true, CSSUnitValue: true, CSSURLImageValue: true, CSSStyleValue: false, CSSMatrixComponent: true, CSSRotation: true, CSSScale: true, CSSSkew: true, CSSTranslation: true, CSSTransformComponent: false, CSSTransformValue: true, CSSUnparsedValue: true, DataTransferItemList: true, DOMException: true, ClientRectList: true, DOMRectList: true, DOMRectReadOnly: false, DOMStringList: true, DOMTokenList: true, MathMLElement: true, SVGAElement: true, SVGAnimateElement: true, SVGAnimateMotionElement: true, SVGAnimateTransformElement: true, SVGAnimationElement: true, SVGCircleElement: true, SVGClipPathElement: true, SVGDefsElement: true, SVGDescElement: true, SVGDiscardElement: true, SVGEllipseElement: true, SVGFEBlendElement: true, SVGFEColorMatrixElement: true, SVGFEComponentTransferElement: true, SVGFECompositeElement: true, SVGFEConvolveMatrixElement: true, SVGFEDiffuseLightingElement: true, SVGFEDisplacementMapElement: true, SVGFEDistantLightElement: true, SVGFEFloodElement: true, SVGFEFuncAElement: true, SVGFEFuncBElement: true, SVGFEFuncGElement: true, SVGFEFuncRElement: true, SVGFEGaussianBlurElement: true, SVGFEImageElement: true, SVGFEMergeElement: true, SVGFEMergeNodeElement: true, SVGFEMorphologyElement: true, SVGFEOffsetElement: true, SVGFEPointLightElement: true, SVGFESpecularLightingElement: true, SVGFESpotLightElement: true, SVGFETileElement: true, SVGFETurbulenceElement: true, SVGFilterElement: true, SVGForeignObjectElement: true, SVGGElement: true, SVGGeometryElement: true, SVGGraphicsElement: true, SVGImageElement: true, SVGLineElement: true, SVGLinearGradientElement: true, SVGMarkerElement: true, SVGMaskElement: true, SVGMetadataElement: true, SVGPathElement: true, SVGPatternElement: true, SVGPolygonElement: true, SVGPolylineElement: true, SVGRadialGradientElement: true, SVGRectElement: true, SVGScriptElement: true, SVGSetElement: true, SVGStopElement: true, SVGStyleElement: true, SVGElement: true, SVGSVGElement: true, SVGSwitchElement: true, SVGSymbolElement: true, SVGTSpanElement: true, SVGTextContentElement: true, SVGTextElement: true, SVGTextPathElement: true, SVGTextPositioningElement: true, SVGTitleElement: true, SVGUseElement: true, SVGViewElement: true, SVGGradientElement: true, SVGComponentTransferFunctionElement: true, SVGFEDropShadowElement: true, SVGMPathElement: true, Element: false, AbsoluteOrientationSensor: true, Accelerometer: true, AccessibleNode: true, AmbientLightSensor: true, Animation: true, ApplicationCache: true, DOMApplicationCache: true, OfflineResourceList: true, BackgroundFetchRegistration: true, BatteryManager: true, BroadcastChannel: true, CanvasCaptureMediaStreamTrack: true, DedicatedWorkerGlobalScope: true, EventSource: true, FileReader: true, FontFaceSet: true, Gyroscope: true, XMLHttpRequest: true, XMLHttpRequestEventTarget: true, XMLHttpRequestUpload: true, LinearAccelerationSensor: true, Magnetometer: true, MediaDevices: true, MediaKeySession: true, MediaQueryList: true, MediaRecorder: true, MediaSource: true, MediaStream: true, MediaStreamTrack: true, MessagePort: true, MIDIAccess: true, MIDIInput: true, MIDIOutput: true, MIDIPort: true, NetworkInformation: true, Notification: true, OffscreenCanvas: true, OrientationSensor: true, PaymentRequest: true, Performance: true, PermissionStatus: true, PresentationAvailability: true, PresentationConnection: true, PresentationConnectionList: true, PresentationRequest: true, RelativeOrientationSensor: true, RemotePlayback: true, RTCDataChannel: true, DataChannel: true, RTCDTMFSender: true, RTCPeerConnection: true, webkitRTCPeerConnection: true, mozRTCPeerConnection: true, ScreenOrientation: true, Sensor: true, ServiceWorker: true, ServiceWorkerContainer: true, ServiceWorkerGlobalScope: true, ServiceWorkerRegistration: true, SharedWorker: true, SharedWorkerGlobalScope: true, SpeechRecognition: true, webkitSpeechRecognition: true, SpeechSynthesis: true, SpeechSynthesisUtterance: true, VR: true, VRDevice: true, VRDisplay: true, VRSession: true, VisualViewport: true, WebSocket: true, Window: true, DOMWindow: true, Worker: true, WorkerGlobalScope: true, WorkerPerformance: true, BluetoothDevice: true, BluetoothRemoteGATTCharacteristic: true, Clipboard: true, MojoInterfaceInterceptor: true, USB: true, IDBDatabase: true, IDBOpenDBRequest: true, IDBVersionChangeRequest: true, IDBRequest: true, IDBTransaction: true, AnalyserNode: true, RealtimeAnalyserNode: true, AudioBufferSourceNode: true, AudioDestinationNode: true, AudioNode: true, AudioScheduledSourceNode: true, AudioWorkletNode: true, BiquadFilterNode: true, ChannelMergerNode: true, AudioChannelMerger: true, ChannelSplitterNode: true, AudioChannelSplitter: true, ConstantSourceNode: true, ConvolverNode: true, DelayNode: true, DynamicsCompressorNode: true, GainNode: true, AudioGainNode: true, IIRFilterNode: true, MediaElementAudioSourceNode: true, MediaStreamAudioDestinationNode: true, MediaStreamAudioSourceNode: true, OscillatorNode: true, Oscillator: true, PannerNode: true, AudioPannerNode: true, webkitAudioPannerNode: true, ScriptProcessorNode: true, JavaScriptAudioNode: true, StereoPannerNode: true, WaveShaperNode: true, EventTarget: false, File: true, FileList: true, FileWriter: true, HTMLFormElement: true, Gamepad: true, History: true, HTMLCollection: true, HTMLFormControlsCollection: true, HTMLOptionsCollection: true, Location: true, MediaList: true, MIDIInputMap: true, MIDIOutputMap: true, MimeType: true, MimeTypeArray: true, Document: true, DocumentFragment: true, HTMLDocument: true, ShadowRoot: true, XMLDocument: true, Attr: true, DocumentType: true, Node: false, NodeList: true, RadioNodeList: true, Plugin: true, PluginArray: true, RTCStatsReport: true, HTMLSelectElement: true, SourceBuffer: true, SourceBufferList: true, SpeechGrammar: true, SpeechGrammarList: true, SpeechRecognitionResult: true, Storage: true, CSSStyleSheet: true, StyleSheet: true, TextTrack: true, TextTrackCue: true, VTTCue: true, TextTrackCueList: true, TextTrackList: true, TimeRanges: true, Touch: true, TouchList: true, TrackDefaultList: true, URL: true, VideoTrackList: true, CSSRuleList: true, ClientRect: true, DOMRect: true, GamepadList: true, NamedNodeMap: true, MozNamedAttrMap: true, SpeechRecognitionResultList: true, StyleSheetList: true, SVGLength: true, SVGLengthList: true, SVGNumber: true, SVGNumberList: true, SVGPointList: true, SVGStringList: true, SVGTransform: true, SVGTransformList: true, AudioBuffer: true, AudioParamMap: true, AudioTrackList: true, AudioContext: true, webkitAudioContext: true, BaseAudioContext: false, OfflineAudioContext: true});
     A.NativeTypedArray.$nativeSuperclassTag = "ArrayBufferView";
     A._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin.$nativeSuperclassTag = "ArrayBufferView";
     A._NativeTypedArrayOfDouble_NativeTypedArray_ListMixin_FixedLengthListMixin.$nativeSuperclassTag = "ArrayBufferView";
@@ -17203,6 +18217,9 @@
   Function.prototype.call$1$2 = function(a, b) {
     return this(a, b);
   };
+  Function.prototype.call$1$0 = function() {
+    return this();
+  };
   Function.prototype.call$2$3 = function(a, b, c) {
     return this(a, b, c);
   };
diff --git a/pkgs/test/lib/src/runner/executable_settings.dart b/pkgs/test/lib/src/runner/executable_settings.dart
index cf073de..cd67b93 100644
--- a/pkgs/test/lib/src/runner/executable_settings.dart
+++ b/pkgs/test/lib/src/runner/executable_settings.dart
@@ -34,10 +34,16 @@
   /// `PROGRAMFILES(X64)` environment variables.
   final String? _windowsExecutable;
 
+  /// The environment variable, if any, to use as an override for the default
+  /// path.
+  final String? _environmentOverride;
+
   /// The path to the executable for the current operating system.
   String get executable {
-    final envVariable = Platform.environment['CHROME_EXECUTABLE'];
-    if (envVariable != null) return envVariable;
+    if (_environmentOverride != null) {
+      final envVariable = Platform.environment[_environmentOverride];
+      if (envVariable != null) return envVariable;
+    }
 
     if (Platform.isMacOS) return _macOSExecutable!;
     if (!Platform.isWindows) return _linuxExecutable!;
@@ -172,11 +178,13 @@
       String? linuxExecutable,
       String? macOSExecutable,
       String? windowsExecutable,
+      String? environmentOverride,
       bool? headless})
       : arguments = arguments == null ? const [] : List.unmodifiable(arguments),
         _linuxExecutable = linuxExecutable,
         _macOSExecutable = macOSExecutable,
         _windowsExecutable = windowsExecutable,
+        _environmentOverride = environmentOverride,
         _headless = headless;
 
   /// Merges [this] with [other], with [other]'s settings taking priority.
diff --git a/pkgs/test/lib/src/runner/node/platform.dart b/pkgs/test/lib/src/runner/node/platform.dart
index e2df55c..9e42fa8 100644
--- a/pkgs/test/lib/src/runner/node/platform.dart
+++ b/pkgs/test/lib/src/runner/node/platform.dart
@@ -11,9 +11,8 @@
 import 'package:package_config/package_config.dart';
 import 'package:path/path.dart' as p;
 import 'package:stream_channel/stream_channel.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/backend.dart'
-    show Runtime, StackTraceMapper, SuitePlatform;
+    show Compiler, Runtime, StackTraceMapper, SuitePlatform;
 import 'package:test_core/src/runner/application_exception.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/dart2js_compiler_pool.dart'; // ignore: implementation_imports
@@ -82,7 +81,11 @@
   @override
   Future<RunnerSuite> load(String path, SuitePlatform platform,
       SuiteConfiguration suiteConfig, Map<String, Object?> message) async {
-    var pair = await _loadChannel(path, platform.runtime, suiteConfig);
+    if (platform.compiler != Compiler.dart2js) {
+      throw StateError(
+          'Unsupported compiler for the Node platform ${platform.compiler}.');
+    }
+    var pair = await _loadChannel(path, platform, suiteConfig);
     var controller = deserializeSuite(
         path, platform, suiteConfig, PluginEnvironment(), pair.first, message);
 
@@ -96,12 +99,14 @@
   /// Returns that channel along with a [StackTraceMapper] representing the
   /// source map for the compiled suite.
   Future<Pair<StreamChannel<Object?>, StackTraceMapper?>> _loadChannel(
-      String path, Runtime runtime, SuiteConfiguration suiteConfig) async {
+      String path,
+      SuitePlatform platform,
+      SuiteConfiguration suiteConfig) async {
     final servers = await _loopback();
 
     try {
-      var pair =
-          await _spawnProcess(path, runtime, suiteConfig, servers.first.port);
+      var pair = await _spawnProcess(
+          path, platform.runtime, suiteConfig, servers.first.port);
       var process = pair.first;
 
       // Forward Node's standard IO to the print handler so it's associated with
@@ -292,7 +297,7 @@
         await _compilers.close();
 
         if (_config.pubServeUrl == null) {
-          Directory(_compiledDir).deleteSync(recursive: true);
+          await Directory(_compiledDir).deleteWithRetry();
         } else {
           _http!.close();
         }
diff --git a/pkgs/test/lib/src/runner/wasm/platform.dart b/pkgs/test/lib/src/runner/wasm/platform.dart
index 437c9bb..803927c 100644
--- a/pkgs/test/lib/src/runner/wasm/platform.dart
+++ b/pkgs/test/lib/src/runner/wasm/platform.dart
@@ -14,8 +14,7 @@
 import 'package:shelf_packages_handler/shelf_packages_handler.dart';
 import 'package:shelf_static/shelf_static.dart';
 import 'package:shelf_web_socket/shelf_web_socket.dart';
-// ignore: deprecated_member_use
-import 'package:test_api/backend.dart' show Runtime, SuitePlatform;
+import 'package:test_api/backend.dart' show Compiler, Runtime, SuitePlatform;
 import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/package_version.dart'; // ignore: implementation_imports
 import 'package:test_core/src/runner/platform.dart'; // ignore: implementation_imports
@@ -201,11 +200,16 @@
   @override
   Future<RunnerSuite?> load(String path, SuitePlatform platform,
       SuiteConfiguration suiteConfig, Map<String, Object?> message) async {
+    if (platform.compiler != Compiler.dart2wasm) {
+      throw StateError(
+          'Unsupported compiler for experimental-chrome-wasm platform '
+          '${platform.compiler}');
+    }
+
     if (suiteConfig.precompiledPath != null) {
       throw UnsupportedError(
           'The wasm platform doesn\'t support precompiled suites');
     }
-
     var browser = platform.runtime;
     assert(suiteConfig.runtimes.contains(browser.identifier));
 
@@ -216,6 +220,7 @@
     // TODO: Support custom html?
 
     Uri suiteUrl;
+
     await _compileSuite(path, suiteConfig);
 
     if (_closed) return null;
@@ -227,7 +232,8 @@
     var browserManager = await _browserManagerFor(browser);
     if (_closed || browserManager == null) return null;
 
-    var suite = await browserManager.load(path, suiteUrl, suiteConfig, message);
+    var suite = await browserManager.load(
+        path, suiteUrl, suiteConfig, message, platform.compiler);
     if (_closed) return null;
     return suite;
   }
@@ -351,9 +357,8 @@
             browser.then((b) => b?.close()),
           _server.close(),
           _compilers.close(),
+          Directory(_compiledDir).deleteWithRetry(),
         ]);
-
-        Directory(_compiledDir).deleteSync(recursive: true);
       });
   final _closeMemo = AsyncMemoizer<void>();
 }
diff --git a/pkgs/test/lib/src/util/path_handler.dart b/pkgs/test/lib/src/util/path_handler.dart
index ee43351..10a8c4e 100644
--- a/pkgs/test/lib/src/util/path_handler.dart
+++ b/pkgs/test/lib/src/util/path_handler.dart
@@ -30,7 +30,7 @@
   void add(String path, shelf.Handler handler) {
     var node = _paths;
     for (var component in p.url.split(path)) {
-      node = node.children.putIfAbsent(component, () => _Node());
+      node = node.children.putIfAbsent(component, _Node.new);
     }
     node.handler = handler;
   }
diff --git a/pkgs/test/lib/test.dart b/pkgs/test/lib/test.dart
index 961dae1..7bcc673 100644
--- a/pkgs/test/lib/test.dart
+++ b/pkgs/test/lib/test.dart
@@ -2,5 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+export 'package:matcher/expect.dart';
+// Deprecated exports not surfaced through focused libraries.
+// ignore: deprecated_member_use
+export 'package:matcher/src/expect/expect.dart' show ErrorFormatter;
+// ignore: deprecated_member_use
+export 'package:matcher/src/expect/expect_async.dart' show expectAsync;
+// ignore: deprecated_member_use
+export 'package:matcher/src/expect/throws_matcher.dart' show Throws, throws;
+// The non-deprecated API (through a deprecated import).
 // ignore: deprecated_member_use
 export 'package:test_core/test_core.dart';
diff --git a/pkgs/test/pubspec.yaml b/pkgs/test/pubspec.yaml
index d232530..872b96a 100644
--- a/pkgs/test/pubspec.yaml
+++ b/pkgs/test/pubspec.yaml
@@ -1,14 +1,14 @@
 name: test
-version: 1.23.0-dev
+version: 1.24.7-wip
 description: >-
   A full featured library for writing and running Dart tests across platforms.
 repository: https://github.com/dart-lang/test/tree/master/pkgs/test
 
 environment:
-  sdk: '>=2.18.0 <3.0.0'
+  sdk: ^3.0.0
 
 dependencies:
-  analyzer: '>=2.0.0 <6.0.0'
+  analyzer: '>=5.12.0 <7.0.0'
   async: ^2.5.0
   boolean_selector: ^2.1.0
   collection: ^1.15.0
@@ -16,6 +16,11 @@
   http_multi_server: ^3.0.0
   io: ^1.0.0
   js: ^0.6.4
+
+  # Use a tight version constraint to ensure that a constraint on matcher
+  # properly constrains all features it provides.
+  matcher: '>=0.12.16 <0.12.17'
+
   node_preamble: ^2.0.0
   package_config: ^2.0.0
   path: ^1.8.0
@@ -27,17 +32,19 @@
   source_span: ^1.8.0
   stack_trace: ^1.10.0
   stream_channel: ^2.1.0
+
+  # Use an exact version until the test_api and test_core package are stable.
+  test_api: 0.6.1
+  test_core: 0.5.6
+
   typed_data: ^1.3.0
   web_socket_channel: ^2.0.0
   webkit_inspection_protocol: ^1.0.0
   yaml: ^3.0.0
-  # Use an exact version until the test_api and test_core package are stable.
-  test_api: 0.4.18
-  test_core: 0.4.23
 
 dev_dependencies:
+  dart_flutter_team_lints: ^1.0.0
   fake_async: ^1.0.0
   glob: ^2.0.0
-  lints: '>=1.0.0 <3.0.0'
   test_descriptor: ^2.0.0
   test_process: ^2.0.0
diff --git a/pkgs/test/test/runner/browser/chrome_test.dart b/pkgs/test/test/runner/browser/chrome_test.dart
index 3e97944..6f291b9 100644
--- a/pkgs/test/test/runner/browser/chrome_test.dart
+++ b/pkgs/test/test/runner/browser/chrome_test.dart
@@ -4,6 +4,7 @@
 
 @TestOn('vm')
 @Tags(['chrome'])
+library;
 
 import 'package:test/src/runner/browser/chrome.dart';
 import 'package:test/src/runner/executable_settings.dart';
diff --git a/pkgs/test/test/runner/browser/code_server.dart b/pkgs/test/test/runner/browser/code_server.dart
index 881aa89..85705cc 100644
--- a/pkgs/test/test/runner/browser/code_server.dart
+++ b/pkgs/test/test/runner/browser/code_server.dart
@@ -9,7 +9,7 @@
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:shelf/shelf_io.dart' as shelf_io;
 import 'package:shelf_web_socket/shelf_web_socket.dart';
-import 'package:test/test.dart' show printOnFailure, TestFailure;
+import 'package:test/test.dart' show TestFailure, printOnFailure;
 import 'package:web_socket_channel/web_socket_channel.dart';
 
 /// A class that serves Dart and/or JS code and receives WebSocket connections.
diff --git a/pkgs/test/test/runner/browser/compact_reporter_test.dart b/pkgs/test/test/runner/browser/compact_reporter_test.dart
index 4d1cbb4..753ffa1 100644
--- a/pkgs/test/test/runner/browser/compact_reporter_test.dart
+++ b/pkgs/test/test/runner/browser/compact_reporter_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
@@ -28,7 +29,7 @@
         ['-p', 'chrome', '-p', 'vm', '-j', '1', 'test.dart'],
         reporter: 'compact');
 
-    expect(test.stdout, containsInOrder(['[Chrome]', '[VM]']));
+    expect(test.stdout, containsInOrder(['[Chrome, Dart2Js]', '[VM, Kernel]']));
     await test.shouldExit(0);
   }, tags: 'chrome');
 }
diff --git a/pkgs/test/test/runner/browser/expanded_reporter_test.dart b/pkgs/test/test/runner/browser/expanded_reporter_test.dart
index dab8d52..875aaba 100644
--- a/pkgs/test/test/runner/browser/expanded_reporter_test.dart
+++ b/pkgs/test/test/runner/browser/expanded_reporter_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
@@ -28,8 +29,8 @@
       'test.dart'
     ]);
 
-    expect(test.stdoutStream(), emitsThrough(contains('[VM]')));
-    expect(test.stdout, emitsThrough(contains('[Chrome]')));
+    expect(test.stdoutStream(), emitsThrough(contains('[VM, Kernel]')));
+    expect(test.stdout, emitsThrough(contains('[Chrome, Dart2Js]')));
     await test.shouldExit(0);
   }, tags: ['chrome']);
 }
diff --git a/pkgs/test/test/runner/browser/firefox_html_test.dart b/pkgs/test/test/runner/browser/firefox_html_test.dart
index 0ba4111..c9a5302 100644
--- a/pkgs/test/test/runner/browser/firefox_html_test.dart
+++ b/pkgs/test/test/runner/browser/firefox_html_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('firefox')
+library;
 
 import 'package:test/src/runner/browser/dom.dart' as dom;
 import 'package:test/test.dart';
diff --git a/pkgs/test/test/runner/browser/firefox_test.dart b/pkgs/test/test/runner/browser/firefox_test.dart
index a1189d8..7aa0074 100644
--- a/pkgs/test/test/runner/browser/firefox_test.dart
+++ b/pkgs/test/test/runner/browser/firefox_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 @TestOn('vm')
 @Tags(['firefox'])
+library;
 
 import 'package:test/src/runner/browser/firefox.dart';
 import 'package:test/src/runner/executable_settings.dart';
@@ -79,4 +80,36 @@
     expect(test.stdout, emitsThrough(contains('-1: Some tests failed.')));
     await test.shouldExit(1);
   });
+
+  test('can override firefox location with FIREFOX_EXECUTABLE var', () async {
+    await d.file('test.dart', '''
+import 'package:test/test.dart';
+
+void main() {
+  test("success", () {});
+}
+''').create();
+    var test = await runTest(['-p', 'firefox', 'test.dart'],
+        environment: {'FIREFOX_EXECUTABLE': '/some/bad/path'});
+    expect(test.stdout, emitsThrough(contains('Failed to run Firefox:')));
+    await test.shouldExit(1);
+  });
+
+  test('not impacted by CHROME_EXECUTABLE var', () async {
+    await d.file('test.dart', '''
+import 'dart:html';
+
+import 'package:test/test.dart';
+
+void main() {
+  test("success", () {
+    assert(window.navigator.vendor != 'Google Inc.');
+  });
+}
+''').create();
+    var test = await runTest(['-p', 'firefox', 'test.dart'],
+        environment: {'CHROME_EXECUTABLE': '/some/bad/path'});
+    expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
+    await test.shouldExit(0);
+  });
 }
diff --git a/pkgs/test/test/runner/browser/internet_explorer_test.dart b/pkgs/test/test/runner/browser/internet_explorer_test.dart
index 9f3f5b8..02fe29e 100644
--- a/pkgs/test/test/runner/browser/internet_explorer_test.dart
+++ b/pkgs/test/test/runner/browser/internet_explorer_test.dart
@@ -4,6 +4,7 @@
 
 @TestOn('vm')
 @Tags(['ie'])
+library;
 
 import 'package:test/src/runner/browser/internet_explorer.dart';
 import 'package:test/src/runner/executable_settings.dart';
diff --git a/pkgs/test/test/runner/browser/loader_test.dart b/pkgs/test/test/runner/browser/loader_test.dart
index 495cf3a..17cdb9a 100644
--- a/pkgs/test/test/runner/browser/loader_test.dart
+++ b/pkgs/test/test/runner/browser/loader_test.dart
@@ -4,6 +4,8 @@
 
 @TestOn('vm')
 @Tags(['chrome'])
+library;
+
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
@@ -67,6 +69,7 @@
     test('returns a suite with the file path and platform', () {
       expect(suite.path, equals(p.join(d.sandbox, 'a_test.dart')));
       expect(suite.platform.runtime, equals(Runtime.chrome));
+      expect(suite.platform.compiler, equals(Runtime.chrome.defaultCompiler));
     });
 
     test('returns tests with the correct names', () {
@@ -142,8 +145,10 @@
         .cast<RunnerSuite>()
         .toList();
     expect(suites[0].platform.runtime, equals(Runtime.vm));
+    expect(suites[0].platform.compiler, equals(Runtime.vm.defaultCompiler));
     expect(suites[0].path, equals(path));
     expect(suites[1].platform.runtime, equals(Runtime.chrome));
+    expect(suites[1].platform.compiler, equals(Runtime.chrome.defaultCompiler));
     expect(suites[1].path, equals(path));
 
     for (var suite in suites) {
diff --git a/pkgs/test/test/runner/browser/microsoft_edge_test.dart b/pkgs/test/test/runner/browser/microsoft_edge_test.dart
new file mode 100644
index 0000000..2d3e4cf
--- /dev/null
+++ b/pkgs/test/test/runner/browser/microsoft_edge_test.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+@TestOn('vm')
+@Tags(['edge'])
+library;
+
+import 'package:test/src/runner/browser/microsoft_edge.dart';
+import 'package:test/src/runner/executable_settings.dart';
+import 'package:test/test.dart';
+import 'package:test_descriptor/test_descriptor.dart' as d;
+
+import '../../io.dart';
+import '../../utils.dart';
+import 'code_server.dart';
+
+void main() {
+  setUpAll(precompileTestExecutable);
+
+  test('starts edge with the given URL', () async {
+    var server = await CodeServer.start();
+
+    server.handleJavaScript('''
+var webSocket = new WebSocket(window.location.href.replace("http://", "ws://"));
+webSocket.addEventListener("open", function() {
+  webSocket.send("loaded!");
+});
+''');
+    var webSocket = server.handleWebSocket();
+
+    var edge = MicrosoftEdge(server.url, configuration());
+    addTearDown(() => edge.close());
+
+    expect(await (await webSocket).stream.first, equals('loaded!'));
+  }, timeout: Timeout.factor(2));
+
+  test('reports an error in onExit', () {
+    var edge = MicrosoftEdge(Uri.parse('https://dart.dev'), configuration(),
+        settings: ExecutableSettings(
+            linuxExecutable: '_does_not_exist',
+            macOSExecutable: '_does_not_exist',
+            windowsExecutable: '_does_not_exist'));
+    expect(
+        edge.onExit,
+        throwsA(isApplicationException(
+            startsWith('Failed to run Edge: $noSuchFileMessage'))));
+  });
+
+  test('can run successful tests', () async {
+    await d.file('test.dart', '''
+import 'package:test/test.dart';
+
+void main() {
+  test("success", () {});
+}
+''').create();
+
+    var test = await runTest(['-p', 'edge', 'test.dart']);
+    expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
+    await test.shouldExit(0);
+  });
+
+  test('can run failing tests', () async {
+    await d.file('test.dart', '''
+import 'package:test/test.dart';
+
+void main() {
+  test("failure", () => throw TestFailure("oh no"));
+}
+''').create();
+
+    var test = await runTest(['-p', 'edge', 'test.dart']);
+    expect(test.stdout, emitsThrough(contains('-1: Some tests failed.')));
+    await test.shouldExit(1);
+  });
+
+  test('can override edge location with MS_EDGE_EXECUTABLE var', () async {
+    await d.file('test.dart', '''
+import 'package:test/test.dart';
+
+void main() {
+  test("success", () {});
+}
+''').create();
+    var test = await runTest(['-p', 'edge', 'test.dart'],
+        environment: {'MS_EDGE_EXECUTABLE': '/some/bad/path'});
+    expect(test.stdout, emitsThrough(contains('Failed to run Edge:')));
+    await test.shouldExit(1);
+  });
+}
diff --git a/pkgs/test/test/runner/browser/runner_test.dart b/pkgs/test/test/runner/browser/runner_test.dart
index c5fcb65..322c24a 100644
--- a/pkgs/test/test/runner/browser/runner_test.dart
+++ b/pkgs/test/test/runner/browser/runner_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:convert';
 
 import 'package:test/test.dart';
@@ -38,7 +40,7 @@
           test.stdout,
           containsInOrder([
             'Error: Compilation failed.',
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": dart2js failed.'
           ]));
       await test.shouldExit(1);
@@ -51,7 +53,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": oh no'
           ]));
       await test.shouldExit(1);
@@ -64,7 +66,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": No top-level main() function defined.'
           ]));
       await test.shouldExit(1);
@@ -77,7 +79,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": Top-level main getter is not a function.'
           ]));
       await test.shouldExit(1);
@@ -90,7 +92,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": Top-level main() function takes arguments.'
           ]));
       await test.shouldExit(1);
@@ -111,7 +113,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": "test.html" must contain '
                 '<script src="packages/test/dart.js"></script>.'
           ]));
@@ -133,7 +135,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": Expected exactly 1 '
                 '<link rel="x-dart-test"> in test.html, found 0.'
           ]));
@@ -157,7 +159,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": Expected exactly 1 '
                 '<link rel="x-dart-test"> in test.html, found 2.'
           ]));
@@ -180,7 +182,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": Expected <link rel="x-dart-test"> in '
                 'test.html to have an "href" attribute.'
           ]));
@@ -203,7 +205,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": Failed to load script at '
           ]));
       await test.shouldExit(1);
@@ -246,7 +248,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": "test.html" must contain '
                 '<script src="packages/test/dart.js"></script>.'
           ]));
@@ -270,7 +272,7 @@
         expect(
             test.stdout,
             containsInOrder([
-              '-1: compiling test.dart [E]',
+              '-1: loading test.dart [E]',
               'Failed to load "test.dart": "html_template.html.tpl" does not exist or is not readable'
             ]));
         await test.shouldExit(1);
@@ -293,7 +295,7 @@
         expect(
             test.stdout,
             containsInOrder([
-              '-1: compiling test.dart [E]',
+              '-1: loading test.dart [E]',
               'Failed to load "test.dart": "html_template.html.tpl" must contain exactly one {{testScript}} placeholder'
             ]));
         await test.shouldExit(1);
@@ -318,7 +320,7 @@
         expect(
             test.stdout,
             containsInOrder([
-              '-1: compiling test.dart [E]',
+              '-1: loading test.dart [E]',
               'Failed to load "test.dart": "html_template.html.tpl" must contain exactly one {{testScript}} placeholder'
             ]));
         await test.shouldExit(1);
@@ -338,7 +340,7 @@
         expect(
             test.stdout,
             containsInOrder([
-              '-1: compiling test.dart [E]',
+              '-1: loading test.dart [E]',
               'Failed to load "test.dart": "html_template.html.tpl" must contain '
                   '<script src="packages/test/dart.js"></script>.'
             ]));
@@ -364,7 +366,7 @@
         expect(
             test.stdout,
             containsInOrder([
-              '-1: compiling test.dart [E]',
+              '-1: loading test.dart [E]',
               'Failed to load "test.dart": template file "test.html" cannot be named '
                   'like the test file.'
             ]));
diff --git a/pkgs/test/test/runner/browser/safari_test.dart b/pkgs/test/test/runner/browser/safari_test.dart
index 7fa839b..d37db95 100644
--- a/pkgs/test/test/runner/browser/safari_test.dart
+++ b/pkgs/test/test/runner/browser/safari_test.dart
@@ -4,6 +4,7 @@
 
 @TestOn('vm')
 @Tags(['safari'])
+library;
 
 import 'package:test/src/runner/browser/safari.dart';
 import 'package:test/src/runner/executable_settings.dart';
@@ -80,4 +81,18 @@
     expect(test.stdout, emitsThrough(contains('-1: Some tests failed.')));
     await test.shouldExit(1);
   });
+
+  test('can override safari location with SAFARI_EXECUTABLE var', () async {
+    await d.file('test.dart', '''
+import 'package:test/test.dart';
+
+void main() {
+  test("success", () {});
+}
+''').create();
+    var test = await runTest(['-p', 'safari', 'test.dart'],
+        environment: {'SAFARI_EXECUTABLE': '/some/bad/path'});
+    expect(test.stdout, emitsThrough(contains('Failed to run Safari:')));
+    await test.shouldExit(1);
+  });
 }
diff --git a/pkgs/test/test/runner/compact_reporter_test.dart b/pkgs/test/test/runner/compact_reporter_test.dart
index 741a10d..c935e02 100644
--- a/pkgs/test/test/runner/compact_reporter_test.dart
+++ b/pkgs/test/test/runner/compact_reporter_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:async';
 import 'dart:io';
diff --git a/pkgs/test/test/runner/compiler_runtime_matrix_test.dart b/pkgs/test/test/runner/compiler_runtime_matrix_test.dart
new file mode 100644
index 0000000..cef5815
--- /dev/null
+++ b/pkgs/test/test/runner/compiler_runtime_matrix_test.dart
@@ -0,0 +1,166 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+@TestOn('vm')
+library;
+
+import 'dart:io';
+
+import 'package:test/test.dart';
+import 'package:test_api/backend.dart';
+import 'package:test_descriptor/test_descriptor.dart' as d;
+
+import '../io.dart';
+
+void main() {
+  setUpAll(() async {
+    await precompileTestExecutable();
+  });
+
+  for (var runtime in Runtime.builtIn) {
+    for (var compiler in runtime.supportedCompilers) {
+      // Ignore the platforms we can't run on this OS.
+      if (runtime == Runtime.internetExplorer && !Platform.isWindows ||
+          runtime == Runtime.safari && !Platform.isMacOS) {
+        continue;
+      }
+      group('--runtime ${runtime.identifier} --compiler ${compiler.identifier}',
+          () {
+        final testArgs = [
+          'test.dart',
+          '-p',
+          runtime.identifier,
+          '-c',
+          compiler.identifier
+        ];
+
+        test('can run passing tests', () async {
+          await d.file('test.dart', _goodTest).create();
+          var test = await runTest(testArgs);
+
+          expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
+          await test.shouldExit(0);
+        });
+
+        test('fails gracefully for invalid code', () async {
+          await d.file('test.dart', _compileErrorTest).create();
+          var test = await runTest(testArgs);
+
+          expect(
+              test.stdout,
+              containsInOrder([
+                "Error: A value of type 'String' can't be assigned to a variable of type 'int'.",
+                "int x = 'hello';",
+              ]));
+
+          await test.shouldExit(1);
+        });
+
+        test('fails gracefully for test failures', () async {
+          await d.file('test.dart', _failingTest).create();
+          var test = await runTest(testArgs);
+
+          expect(
+              test.stdout,
+              containsInOrder([
+                'Expected: <2>',
+                'Actual: <1>',
+                'test.dart 5',
+                '+0 -1: Some tests failed.',
+              ]));
+
+          await test.shouldExit(1);
+        });
+
+        test('fails gracefully if a test file throws in main', () async {
+          await d.file('test.dart', _throwingTest).create();
+          var test = await runTest(testArgs);
+          expect(
+              test.stdout,
+              containsInOrder([
+                '-1: [${runtime.name}, ${compiler.name}] loading test.dart [E]',
+                'Failed to load "test.dart": oh no'
+              ]));
+          await test.shouldExit(1);
+        });
+
+        test('captures prints', () async {
+          await d.file('test.dart', _testWithPrints).create();
+          var test = await runTest([...testArgs, '-r', 'json']);
+
+          expect(
+              test.stdout,
+              containsInOrder([
+                '"messageType":"print","message":"hello","type":"print"',
+              ]));
+
+          await test.shouldExit(0);
+        });
+
+        if (runtime.isDartVM) {
+          test('forwards stdout/stderr', () async {
+            await d.file('test.dart', _testWithStdOutAndErr).create();
+            var test = await runTest(testArgs);
+
+            expect(test.stdout, emitsThrough('hello'));
+            expect(test.stderr, emits('world'));
+            await test.shouldExit(0);
+          });
+        }
+      },
+          skip: compiler == Compiler.dart2wasm
+              ? 'Wasm tests are experimental and require special setup'
+              : [Runtime.firefox, Runtime.nodeJS, Runtime.internetExplorer]
+                          .contains(runtime) &&
+                      Platform.isWindows
+                  ? 'https://github.com/dart-lang/test/issues/1942'
+                  : null);
+    }
+  }
+}
+
+final _goodTest = '''
+  import 'package:test/test.dart';
+
+  void main() {
+    test("success", () {});
+  }
+''';
+
+final _failingTest = '''
+  import 'package:test/test.dart';
+
+  void main() {
+    test("failure", () {
+      expect(1, 2);
+    });
+  }
+''';
+
+final _compileErrorTest = '''
+int x = 'hello';
+
+void main() {}
+''';
+
+final _throwingTest = "void main() => throw 'oh no';";
+
+final _testWithPrints = '''
+import 'package:test/test.dart';
+
+void main() {
+  print('hello');
+  test('success', () {});
+}''';
+
+final _testWithStdOutAndErr = '''
+import 'dart:io';
+import 'package:test/test.dart';
+
+void main() async {
+  stdout.writeln('hello');
+  await stdout.flush();
+  stderr.writeln('world');
+  test('success', () {});
+}''';
diff --git a/pkgs/test/test/runner/compiler_test.dart b/pkgs/test/test/runner/compiler_test.dart
new file mode 100644
index 0000000..5cf7a47
--- /dev/null
+++ b/pkgs/test/test/runner/compiler_test.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+@TestOn('vm')
+library;
+
+import 'package:test/test.dart';
+import 'package:test_descriptor/test_descriptor.dart' as d;
+
+import '../io.dart';
+
+final _test = '''
+  import 'package:test/test.dart';
+
+  void main() {
+    test("success", () {});
+  }
+''';
+
+void main() {
+  setUpAll(() async {
+    await precompileTestExecutable();
+    await d.file('test.dart', _test).create();
+  });
+
+  group('--compiler', () {
+    test(
+        'uses the default compiler if none other is specified for the platform',
+        () async {
+      var test =
+          await runTest(['test.dart', '-p', 'chrome,vm', '-c', 'dart2js']);
+
+      expect(test.stdout, emitsThrough(contains('[Chrome, Dart2Js]')));
+      expect(test.stdout, emitsThrough(contains('[VM, Kernel]')));
+      expect(test.stdout, emitsThrough(contains('+2: All tests passed!')));
+      await test.shouldExit(0);
+    });
+
+    test('runs all supported compiler and platform combinations', () async {
+      var test = await runTest(
+          ['test.dart', '-p', 'chrome,vm', '-c', 'dart2js,kernel,source']);
+
+      expect(test.stdout, emitsThrough(contains('[Chrome, Dart2Js]')));
+      expect(test.stdout, emitsThrough(contains('[VM, Kernel]')));
+      expect(test.stdout, emitsThrough(contains('[VM, Source]')));
+      expect(test.stdout, emitsThrough(contains('+3: All tests passed!')));
+      await test.shouldExit(0);
+    });
+
+    test('supports platform selectors', () async {
+      var test = await runTest(
+          ['test.dart', '-p', 'vm', '-c', 'vm:source,browser:kernel']);
+
+      expect(test.stdout, emitsThrough(contains('[VM, Source]')));
+      expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
+      await test.shouldExit(0);
+    });
+
+    test(
+        'will only run a given test once for each compiler, even if there are '
+        'multiple matches', () async {
+      var test =
+          await runTest(['test.dart', '-p', 'vm', '-c', 'vm:source,source']);
+
+      expect(test.stdout, emitsThrough(contains('[VM, Source]')));
+      expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
+      await test.shouldExit(0);
+    });
+
+    test('fails on unknown compilers', () async {
+      var test = await runTest(['test.dart', '-c', 'fake']);
+      expect(test.stderr, emitsThrough(contains('Invalid compiler `fake`')));
+      await test.shouldExit(64);
+    });
+  });
+}
diff --git a/pkgs/test/test/runner/configuration/compiler_test.dart b/pkgs/test/test/runner/configuration/compiler_test.dart
new file mode 100644
index 0000000..d8f8d33
--- /dev/null
+++ b/pkgs/test/test/runner/configuration/compiler_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+@TestOn('vm')
+library;
+
+import 'dart:convert';
+
+import 'package:test/test.dart';
+import 'package:test_descriptor/test_descriptor.dart' as d;
+
+import '../../io.dart';
+
+void main() {
+  setUpAll(precompileTestExecutable);
+
+  group('compilers', () {
+    test('uses specified compilers for supporting platforms', () async {
+      await d
+          .file(
+              'dart_test.yaml',
+              jsonEncode({
+                'compilers': ['source']
+              }))
+          .create();
+
+      await d.file('test.dart', '''
+        import 'package:test/test.dart';
+
+        void main() {
+          test("test", () {});
+        }
+      ''').create();
+
+      var test = await runTest(['-p', 'chrome,vm', 'test.dart']);
+      expect(
+          test.stdout,
+          containsInOrder([
+            '+0: [Chrome, Dart2Js]',
+            '+1: [VM, Source]',
+            '+2: All tests passed!',
+          ]));
+      await test.shouldExit(0);
+    });
+
+    test('supports platform selectors with compilers', () async {
+      await d
+          .file(
+              'dart_test.yaml',
+              jsonEncode({
+                'compilers': ['vm:source', 'browser:kernel']
+              }))
+          .create();
+
+      await d.file('test.dart', '''
+        import 'package:test/test.dart';
+
+        void main() {
+          test("test", () {});
+        }
+      ''').create();
+
+      var test = await runTest(['-p', 'chrome,vm', 'test.dart']);
+      expect(
+          test.stdout,
+          containsInOrder([
+            '+0: [Chrome, Dart2Js]',
+            '+1: [VM, Source]',
+            '+2: All tests passed!',
+          ]));
+      await test.shouldExit(0);
+    });
+  });
+}
diff --git a/pkgs/test/test/runner/configuration/configuration_test.dart b/pkgs/test/test/runner/configuration/configuration_test.dart
index 4b360be..3e09082 100644
--- a/pkgs/test/test/runner/configuration/configuration_test.dart
+++ b/pkgs/test/test/runner/configuration/configuration_test.dart
@@ -3,9 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'package:boolean_selector/boolean_selector.dart';
 import 'package:test/test.dart';
-
 import 'package:test_core/src/runner/configuration/reporters.dart';
 import 'package:test_core/src/runner/suite.dart';
 import 'package:test_core/src/util/io.dart';
diff --git a/pkgs/test/test/runner/configuration/custom_platform_test.dart b/pkgs/test/test/runner/configuration/custom_platform_test.dart
index af3721d..ca9ec05 100644
--- a/pkgs/test/test/runner/configuration/custom_platform_test.dart
+++ b/pkgs/test/test/runner/configuration/custom_platform_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:io';
 
diff --git a/pkgs/test/test/runner/configuration/duplicate_names_test.dart b/pkgs/test/test/runner/configuration/duplicate_names_test.dart
index d9afc44..5a02f52 100644
--- a/pkgs/test/test/runner/configuration/duplicate_names_test.dart
+++ b/pkgs/test/test/runner/configuration/duplicate_names_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:convert';
 
 import 'package:path/path.dart' as p;
diff --git a/pkgs/test/test/runner/configuration/global_test.dart b/pkgs/test/test/runner/configuration/global_test.dart
index 930be57..6d3e76b 100644
--- a/pkgs/test/test/runner/configuration/global_test.dart
+++ b/pkgs/test/test/runner/configuration/global_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:convert';
 
 import 'package:test/test.dart';
diff --git a/pkgs/test/test/runner/configuration/include_test.dart b/pkgs/test/test/runner/configuration/include_test.dart
index 6c91503..5d064cf 100644
--- a/pkgs/test/test/runner/configuration/include_test.dart
+++ b/pkgs/test/test/runner/configuration/include_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 import 'package:test_core/src/runner/configuration.dart';
diff --git a/pkgs/test/test/runner/configuration/platform_test.dart b/pkgs/test/test/runner/configuration/platform_test.dart
index 0a9f427..014c0ed 100644
--- a/pkgs/test/test/runner/configuration/platform_test.dart
+++ b/pkgs/test/test/runner/configuration/platform_test.dart
@@ -3,8 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:convert';
-import 'dart:io';
 
 import 'package:test/test.dart';
 import 'package:test_core/src/util/exit_codes.dart' as exit_codes;
@@ -42,7 +43,7 @@
       expect(
           test.stdout,
           containsInOrder(
-              ['-1: [Chrome] test [E]', '+1 -1: Some tests failed.']));
+              ['-1: [Chrome, Dart2Js] test [E]', '+1 -1: Some tests failed.']));
       await test.shouldExit(1);
     }, tags: ['chrome']);
 
@@ -71,8 +72,8 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: [Chrome] test [E]',
-            '-2: [VM] test [E]',
+            '-1: [Chrome, Dart2Js] test [E]',
+            '-2: [VM, Kernel] test [E]',
             '-2: Some tests failed.'
           ]));
       await test.shouldExit(1);
@@ -205,10 +206,8 @@
       var test = await runTest(['.']);
       expect(
           test.stdout,
-          containsInOrder([
-            '+0: .${Platform.pathSeparator}test_foo.dart: test_foo',
-            '+1: All tests passed!'
-          ]));
+          containsInOrder(
+              ['+0: ./test_foo.dart: test_foo', '+1: All tests passed!']));
       await test.shouldExit(0);
     });
 
@@ -243,10 +242,8 @@
       var test = await runTest(['.']);
       expect(
           test.stdout,
-          containsInOrder([
-            '+0: .${Platform.pathSeparator}foo_test.dart: foo_test',
-            '+1: All tests passed!'
-          ]));
+          containsInOrder(
+              ['+0: ./foo_test.dart: foo_test', '+1: All tests passed!']));
       await test.shouldExit(0);
     });
 
diff --git a/pkgs/test/test/runner/configuration/presets_test.dart b/pkgs/test/test/runner/configuration/presets_test.dart
index 01568e4..193f12e 100644
--- a/pkgs/test/test/runner/configuration/presets_test.dart
+++ b/pkgs/test/test/runner/configuration/presets_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:convert';
 
 import 'package:test/test.dart';
diff --git a/pkgs/test/test/runner/configuration/randomize_order_test.dart b/pkgs/test/test/runner/configuration/randomize_order_test.dart
index c7cf3f1..690f54b 100644
--- a/pkgs/test/test/runner/configuration/randomize_order_test.dart
+++ b/pkgs/test/test/runner/configuration/randomize_order_test.dart
@@ -3,8 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:convert';
-import 'dart:io';
 
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
@@ -148,14 +149,14 @@
         test.stdout,
         emitsInAnyOrder([
           containsInOrder([
-            '.${Platform.pathSeparator}1_test.dart: test 1.2',
-            '.${Platform.pathSeparator}1_test.dart: test 1.3',
-            '.${Platform.pathSeparator}1_test.dart: test 1.1'
+            './1_test.dart: test 1.2',
+            './1_test.dart: test 1.3',
+            './1_test.dart: test 1.1'
           ]),
           containsInOrder([
-            '.${Platform.pathSeparator}2_test.dart: test 2.2',
-            '.${Platform.pathSeparator}2_test.dart: test 2.3',
-            '.${Platform.pathSeparator}2_test.dart: test 2.1'
+            './2_test.dart: test 2.2',
+            './2_test.dart: test 2.3',
+            './2_test.dart: test 2.1'
           ]),
           contains('+6: All tests passed!')
         ]));
diff --git a/pkgs/test/test/runner/configuration/suite_test.dart b/pkgs/test/test/runner/configuration/suite_test.dart
index a8e13cb..1c2fc62 100644
--- a/pkgs/test/test/runner/configuration/suite_test.dart
+++ b/pkgs/test/test/runner/configuration/suite_test.dart
@@ -3,11 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'package:boolean_selector/boolean_selector.dart';
 import 'package:test/test.dart';
-
 import 'package:test_api/src/backend/platform_selector.dart';
 import 'package:test_api/src/backend/runtime.dart';
+import 'package:test_core/src/runner/compiler_selection.dart';
 import 'package:test_core/src/runner/runtime_selection.dart';
 
 import '../../utils.dart';
@@ -21,6 +23,7 @@
         expect(merged.runSkipped, isFalse);
         expect(merged.precompiledPath, isNull);
         expect(merged.runtimes, equals([Runtime.vm.identifier]));
+        expect(merged.compilerSelections, isNull);
       });
 
       test("if only the old configuration's is defined, uses it", () {
@@ -28,13 +31,16 @@
                 jsTrace: true,
                 runSkipped: true,
                 precompiledPath: '/tmp/js',
-                runtimes: [RuntimeSelection(Runtime.chrome.identifier)])
+                runtimes: [RuntimeSelection(Runtime.chrome.identifier)],
+                compilerSelections: [CompilerSelection.parse('dart2js')])
             .merge(suiteConfiguration());
 
         expect(merged.jsTrace, isTrue);
         expect(merged.runSkipped, isTrue);
         expect(merged.precompiledPath, equals('/tmp/js'));
         expect(merged.runtimes, equals([Runtime.chrome.identifier]));
+        expect(merged.compilerSelections,
+            equals([CompilerSelection.parse('dart2js')]));
       });
 
       test("if only the configuration's is defined, uses it", () {
@@ -42,12 +48,15 @@
             jsTrace: true,
             runSkipped: true,
             precompiledPath: '/tmp/js',
-            runtimes: [RuntimeSelection(Runtime.chrome.identifier)]));
+            runtimes: [RuntimeSelection(Runtime.chrome.identifier)],
+            compilerSelections: [CompilerSelection.parse('dart2js')]));
 
         expect(merged.jsTrace, isTrue);
         expect(merged.runSkipped, isTrue);
         expect(merged.precompiledPath, equals('/tmp/js'));
         expect(merged.runtimes, equals([Runtime.chrome.identifier]));
+        expect(merged.compilerSelections,
+            equals([CompilerSelection.parse('dart2js')]));
       });
 
       test(
@@ -57,18 +66,22 @@
             jsTrace: false,
             runSkipped: true,
             precompiledPath: '/tmp/js',
-            runtimes: [RuntimeSelection(Runtime.chrome.identifier)]);
+            runtimes: [RuntimeSelection(Runtime.chrome.identifier)],
+            compilerSelections: [CompilerSelection.parse('dart2js')]);
         var newer = suiteConfiguration(
             jsTrace: true,
             runSkipped: false,
             precompiledPath: '../js',
-            runtimes: [RuntimeSelection(Runtime.firefox.identifier)]);
+            runtimes: [RuntimeSelection(Runtime.firefox.identifier)],
+            compilerSelections: [CompilerSelection.parse('source')]);
         var merged = older.merge(newer);
 
         expect(merged.jsTrace, isTrue);
         expect(merged.runSkipped, isFalse);
         expect(merged.precompiledPath, equals('../js'));
         expect(merged.runtimes, equals([Runtime.firefox.identifier]));
+        expect(merged.compilerSelections,
+            equals([CompilerSelection.parse('source')]));
       });
     });
 
diff --git a/pkgs/test/test/runner/configuration/tags_test.dart b/pkgs/test/test/runner/configuration/tags_test.dart
index e3aace3..bbdb1d1 100644
--- a/pkgs/test/test/runner/configuration/tags_test.dart
+++ b/pkgs/test/test/runner/configuration/tags_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:convert';
 
diff --git a/pkgs/test/test/runner/configuration/top_level_error_test.dart b/pkgs/test/test/runner/configuration/top_level_error_test.dart
index ea2ffbe..abe5d01 100644
--- a/pkgs/test/test/runner/configuration/top_level_error_test.dart
+++ b/pkgs/test/test/runner/configuration/top_level_error_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:convert';
 
 import 'package:test/test.dart';
@@ -273,7 +275,7 @@
 
       var test = await runTest(['test.dart']);
       expect(test.stderr,
-          containsInOrder(['Invalid name: Unterminated group(foo', '^^^^^^']));
+          containsInOrder(['Invalid name: Unterminated group', '^^^^^^']));
       await test.shouldExit(exit_codes.data);
     });
   });
diff --git a/pkgs/test/test/runner/configuration/top_level_test.dart b/pkgs/test/test/runner/configuration/top_level_test.dart
index af0c644..8158cc5 100644
--- a/pkgs/test/test/runner/configuration/top_level_test.dart
+++ b/pkgs/test/test/runner/configuration/top_level_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:async';
 import 'dart:convert';
@@ -481,7 +482,8 @@
     ''').create();
 
     var test = await runTest(['test.dart']);
-    expect(test.stdout, containsInOrder(['[VM] success', '[Chrome] success']));
+    expect(test.stdout,
+        containsInOrder(['[VM, Kernel] success', '[Chrome, Dart2Js] success']));
     await test.shouldExit(0);
   }, tags: 'chrome');
 
diff --git a/pkgs/test/test/runner/coverage_test.dart b/pkgs/test/test/runner/coverage_test.dart
index 398be5d..b149345 100644
--- a/pkgs/test/test/runner/coverage_test.dart
+++ b/pkgs/test/test/runner/coverage_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:convert';
 import 'dart:io';
diff --git a/pkgs/test/test/runner/data_isolate_strategy_test.dart b/pkgs/test/test/runner/data_isolate_strategy_test.dart
deleted file mode 100644
index a19bf1f..0000000
--- a/pkgs/test/test/runner/data_isolate_strategy_test.dart
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@TestOn('vm')
-
-import 'dart:convert';
-import 'dart:isolate';
-
-import 'package:package_config/package_config.dart';
-import 'package:test/test.dart';
-import 'package:test_descriptor/test_descriptor.dart' as d;
-
-import '../io.dart';
-
-void main() {
-  late PackageConfig currentPackageConfig;
-
-  setUpAll(() async {
-    await precompileTestExecutable();
-    currentPackageConfig =
-        await loadPackageConfigUri((await Isolate.packageConfig)!);
-  });
-
-  setUp(() async {
-    await d
-        .file('package_config.json',
-            jsonEncode(PackageConfig.toJson(currentPackageConfig)))
-        .create();
-  });
-
-  group('The data isolate strategy', () {
-    test('can be enabled', () async {
-      // We confirm it is enabled by checking the error output for an invalid
-      // test, it looks a bit different.
-      await d.file('test.dart', 'invalid Dart file').create();
-      var test = await runTest(['--use-data-isolate-strategy', 'test.dart']);
-
-      expect(
-          test.stdout,
-          containsInOrder([
-            'Failed to load "test.dart":',
-            "Unable to spawn isolate: test.dart:1:9: Error: Expected ';' after this.",
-            'invalid Dart file'
-          ]));
-
-      await test.shouldExit(1);
-    });
-
-    test('can run tests', () async {
-      await d.file('test.dart', '''
-import 'package:test/test.dart';
-
-void main() {
-  test('true is true', () {
-    expect(true, isTrue);
-  });
-}
-      ''').create();
-      var test = await runTest(['--use-data-isolate-strategy', 'test.dart']);
-
-      expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
-      await test.shouldExit(0);
-    });
-  });
-}
diff --git a/pkgs/test/test/runner/engine_test.dart b/pkgs/test/test/runner/engine_test.dart
index 189c548..428ca0f 100644
--- a/pkgs/test/test/runner/engine_test.dart
+++ b/pkgs/test/test/runner/engine_test.dart
@@ -129,6 +129,19 @@
     expect(engine.run(), completion(isFalse));
   });
 
+  test('.run() does not run more tests after failure for stopOnFirstFailure',
+      () async {
+    var secondTestRan = false;
+    var engine = declareEngine(() {
+      test('failure', () => throw 'oh no');
+      test('subsequent', () {
+        secondTestRan = true;
+      });
+    }, stopOnFirstFailure: true);
+    await expectLater(engine.run(), completion(isFalse));
+    expect(secondTestRan, false);
+  });
+
   test('.run() may not be called more than once', () {
     var engine = Engine.withSuites([]);
     expect(engine.run(), completes);
diff --git a/pkgs/test/test/runner/expanded_reporter_test.dart b/pkgs/test/test/runner/expanded_reporter_test.dart
index 5471fd1..1c11686 100644
--- a/pkgs/test/test/runner/expanded_reporter_test.dart
+++ b/pkgs/test/test/runner/expanded_reporter_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:async';
 
@@ -27,6 +28,7 @@
         test('success 1', () {});
         test('success 2', () {});
         test('success 3', () {});''', '''
+        +0: loading test.dart
         +0: success 1
         +1: success 2
         +2: success 3
@@ -38,6 +40,7 @@
         test('failure 1', () => throw TestFailure('oh no'));
         test('failure 2', () => throw TestFailure('oh no'));
         test('failure 3', () => throw TestFailure('oh no'));''', '''
+        +0: loading test.dart
         +0: failure 1
         +0 -1: failure 1 [E]
           oh no
@@ -78,6 +81,7 @@
         test('success 1', () {});
         test('failure 2', () => throw TestFailure('oh no'));
         test('success 2', () {});''', '''
+        +0: loading test.dart
         +0: failure 1
         +0 -1: failure 1 [E]
           oh no
@@ -99,6 +103,7 @@
            'really gosh dang long test name. Even longer than that. No, yet '
                'longer. A little more... okay, that should do it.',
            () {});''', '''
+        +0: loading test.dart
         +0: really gosh dang long test name. Even longer than that. No, yet longer. A little more... okay, that should do it.
         +1: All tests passed!''');
   });
@@ -115,6 +120,7 @@
           Future.microtask(completer.complete);
         });
         test('wait', () => completer.future);''', '''
+        +0: loading test.dart
         +0: failures
         +0 -1: failures [E]
           first error
@@ -148,6 +154,7 @@
           print("three");
           print("four");
         });''', '''
+        +0: loading test.dart
         +0: test
         one
         two
@@ -176,6 +183,7 @@
           waitStarted.complete();
           return testDone.future;
         });''', '''
+        +0: loading test.dart
         +0: test
         +1: wait
         +1: test
@@ -210,6 +218,7 @@
         });
 
         test('wait', () => completer.future);''', '''
+        +0: loading test.dart
         +0: test
         one
         two
@@ -238,6 +247,7 @@
           test('skip 1', () {}, skip: true);
           test('skip 2', () {}, skip: true);
           test('skip 3', () {}, skip: true);''', '''
+          +0: loading test.dart
           +0: skip 1
           +0 ~1: skip 2
           +0 ~2: skip 3
@@ -251,6 +261,7 @@
             test('test 2', () {});
             test('test 3', () {});
           }, skip: true);''', '''
+          +0: loading test.dart
           +0: skip test 1
           +0 ~1: skip test 2
           +0 ~2: skip test 3
@@ -263,6 +274,7 @@
           test('success 1', () {});
           test('skip 2', () {}, skip: true);
           test('success 2', () {});''', '''
+          +0: loading test.dart
           +0: skip 1
           +0 ~1: success 1
           +1 ~1: skip 2
@@ -278,6 +290,7 @@
           test('failure 2', () => throw TestFailure('oh no'));
           test('skip 2', () {}, skip: true);
           test('success 2', () {});''', '''
+          +0: loading test.dart
           +0: failure 1
           +0 -1: failure 1 [E]
             oh no
@@ -299,6 +312,7 @@
       return _expectReport('''
           test('skip 1', () {}, skip: 'some reason');
           test('skip 2', () {}, skip: 'or another');''', '''
+          +0: loading test.dart
           +0: skip 1
             Skip: some reason
           +0 ~1: skip 2
@@ -310,6 +324,7 @@
       return _expectReport('''
           test('skip 1', () {}, skip: 'some reason');
           test('skip 2', () {}, skip: 'or another');''', '''
+          +0: loading test.dart
           +0: skip 1
           +1: skip 2
           +2: All tests passed!''', args: ['--run-skipped']);
@@ -319,6 +334,7 @@
   test('Directs users to enable stack trace chaining if disabled', () async {
     await _expectReport(
         '''test('failure 1', () => throw TestFailure('oh no'));''', '''
+        +0: loading test.dart
         +0: failure 1
         +0 -1: failure 1 [E]
           oh no
diff --git a/pkgs/test/test/runner/github_reporter_test.dart b/pkgs/test/test/runner/github_reporter_test.dart
index ba094fb..db50058 100644
--- a/pkgs/test/test/runner/github_reporter_test.dart
+++ b/pkgs/test/test/runner/github_reporter_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:async';
 
@@ -36,8 +37,8 @@
   test('includes the platform name when multiple platforms are run', () {
     return _expectReportLines('''
         test('success 1', () {});''', [
-      '✅ [VM] success 1',
-      '✅ [Chrome] success 1',
+      '✅ [VM, Kernel] success 1',
+      '✅ [Chrome, Dart2Js] success 1',
       '🎉 2 tests passed.',
     ], args: [
       '-p',
@@ -154,8 +155,9 @@
         test.dart 8:62  main.<fn>.<fn>
         ::endgroup::
         ::group::❌ fail after completion (failed after test completion)
-        This test failed after it had already completed. Make sure to use [expectAsync]
-        or the [completes] matcher when testing async code.
+        This test failed after it had already completed.
+        Make sure to use a matching library which informs the test runner
+        of pending async work.
         test.dart 8:62  main.<fn>.<fn>
         ::endgroup::
         ✅ second test so that the first failure is reported
diff --git a/pkgs/test/test/runner/json_file_reporter_test.dart b/pkgs/test/test/runner/json_file_reporter_test.dart
index a4da453..ce3bd42 100644
--- a/pkgs/test/test/runner/json_file_reporter_test.dart
+++ b/pkgs/test/test/runner/json_file_reporter_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:async';
 import 'dart:io';
@@ -24,6 +25,7 @@
       test('success 2', () {});
       test('success 3', () {});
     ''', '''
+      +0: loading test.dart
       +0: success 1
       +1: success 2
       +2: success 3
@@ -51,6 +53,7 @@
       test('failure 2', () => throw new TestFailure('oh no'));
       test('failure 3', () => throw new TestFailure('oh no'));
     ''', '''
+      +0: loading test.dart
       +0: failure 1
       +0 -1: failure 1 [E]
         oh no
diff --git a/pkgs/test/test/runner/json_reporter_test.dart b/pkgs/test/test/runner/json_reporter_test.dart
index 029d557..a771438 100644
--- a/pkgs/test/test/runner/json_reporter_test.dart
+++ b/pkgs/test/test/runner/json_reporter_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:async';
 
@@ -172,9 +173,9 @@
         errorJson(3, 'oh no'),
         errorJson(
             3,
-            'This test failed after it had already completed. Make sure to '
-            'use [expectAsync]\n'
-            'or the [completes] matcher when testing async code.'),
+            'This test failed after it had already completed.\n'
+            'Make sure to use a matching library which informs the '
+            'test runner\nof pending async work.'),
         testDoneJson(4),
       ]
     ], doneJson(success: false));
@@ -494,7 +495,7 @@
           [
             [
               suiteJson(0, platform: 'chrome'),
-              testStartJson(1, 'compiling test.dart', groupIDs: []),
+              testStartJson(1, 'loading test.dart', groupIDs: []),
               printJson(
                   1,
                   isA<String>().having((s) => s.split('\n'), 'lines',
@@ -511,7 +512,7 @@
           args: ['-p', 'chrome']);
     }, tags: ['chrome'], skip: 'https://github.com/dart-lang/test/issues/872');
 
-    test('the root suite if applicable', () {
+    test('the root suite from a relative path', () {
       return _expectReport(
           '''
       customTest('success 1', () {});
@@ -546,6 +547,46 @@
 ''',
           });
     });
+
+    test('the root suite from an absolute path', () {
+      final path = p.prettyUri(p.join(d.sandbox, 'test.dart'));
+      return _expectReport(
+          '''
+      customTest('success 1', () {});
+      test('success 2', () {});
+    ''',
+          useRelativePath: false,
+          [
+            [
+              suiteJson(0, path: equalsIgnoringCase(path)),
+              testStartJson(
+                  1, allOf(startsWith('loading '), endsWith('test.dart')),
+                  groupIDs: []),
+              testDoneJson(1, hidden: true),
+            ],
+            [
+              groupJson(2, testCount: 2),
+              testStartJson(3, 'success 1',
+                  line: 3,
+                  column: 60,
+                  url: p.toUri(p.join(d.sandbox, 'common.dart')).toString(),
+                  rootColumn: 7,
+                  rootLine: 7,
+                  rootUrl: p.toUri(p.join(d.sandbox, 'test.dart')).toString()),
+              testDoneJson(3),
+              testStartJson(4, 'success 2', line: 8, column: 7),
+              testDoneJson(4),
+            ]
+          ],
+          doneJson(),
+          externalLibraries: {
+            'common.dart': '''
+import 'package:test/test.dart';
+
+void customTest(String name, dynamic Function() testFn) => test(name, testFn);
+''',
+          });
+    });
   });
 
   test(
@@ -558,7 +599,7 @@
         [
           [
             suiteJson(0, platform: 'chrome'),
-            testStartJson(1, 'compiling test.dart', groupIDs: []),
+            testStartJson(1, 'loading test.dart', groupIDs: []),
             printJson(
                 1,
                 isA<String>().having((s) => s.split('\n'), 'lines',
@@ -585,6 +626,7 @@
 Future<void> _expectReport(String tests,
     List<List<Object /*Map|Matcher*/ >> expected, Map<Object, Object> done,
     {List<String> args = const [],
+    bool useRelativePath = true,
     Map<String, String> externalLibraries = const {}}) async {
   var testContent = StringBuffer('''
 import 'dart:async';
@@ -602,8 +644,9 @@
     ..writeln('}');
 
   await d.file('test.dart', testContent.toString()).create();
+  var testPath = useRelativePath ? 'test.dart' : p.join(d.sandbox, 'test.dart');
 
-  var test = await runTest(['test.dart', '--chain-stack-traces', ...args],
+  var test = await runTest([testPath, '--chain-stack-traces', ...args],
       reporter: 'json');
   await test.shouldExit();
 
diff --git a/pkgs/test/test/runner/json_reporter_utils.dart b/pkgs/test/test/runner/json_reporter_utils.dart
index 816cb26..bbdbb78 100644
--- a/pkgs/test/test/runner/json_reporter_utils.dart
+++ b/pkgs/test/test/runner/json_reporter_utils.dart
@@ -24,12 +24,15 @@
   expect(outputLines,
       hasLength(expected.fold<int>(3, (int a, m) => a + m.length)));
 
-  dynamic decodeLine(String l) => jsonDecode(l)
-    ..remove('time')
-    ..remove('stackTrace');
+  final decoded = [
+    for (final line in outputLines)
+      (jsonDecode(line) as Map)
+        ..remove('time')
+        ..remove('stackTrace')
+  ];
 
   // Should contain all suites message.
-  expect(outputLines.map(decodeLine), containsAll([allSuitesJson()]));
+  expect(decoded, containsAll([_allSuitesJson()]));
 
   // A single start event is emitted first.
   final start = {
@@ -38,13 +41,13 @@
     'runnerVersion': testVersion,
     'pid': testPid,
   };
-  expect(decodeLine(outputLines.first), equals(start));
+  expect(decoded.first, equals(start));
 
   // A single done event is emitted last.
-  expect(decodeLine(outputLines.last), equals(done));
+  expect(decoded.last, equals(done));
 
   for (var value in expected) {
-    expect(outputLines.map(decodeLine), containsAllInOrder(value));
+    expect(decoded, containsAllInOrder(value));
   }
 }
 
@@ -52,25 +55,24 @@
 /// all suites.
 ///
 /// The [count] defaults to 1.
-Map<String, Object> allSuitesJson({int count = 1}) {
-  return {'type': 'allSuites', 'count': count};
-}
+Map<String, Object> _allSuitesJson({int count = 1}) =>
+    {'type': 'allSuites', 'count': count};
 
 /// Returns the event emitted by the JSON reporter indicating that a suite has
 /// begun running.
 ///
-/// The [platform] defaults to `"vm"`, the [path] defaults to `"test.dart"`.
+/// The [platform] defaults to `'vm'`.
+/// The [path] defaults to `equals('test.dart')`.
 Map<String, Object> suiteJson(int id,
-    {String platform = 'vm', String path = 'test.dart'}) {
-  return {
-    'type': 'suite',
-    'suite': {
-      'id': id,
-      'platform': platform,
-      'path': path,
-    }
-  };
-}
+        {String platform = 'vm', Matcher? path}) =>
+    {
+      'type': 'suite',
+      'suite': {
+        'id': id,
+        'platform': platform,
+        'path': path ?? 'test.dart',
+      }
+    };
 
 /// Returns the event emitted by the JSON reporter indicating that a group has
 /// begun running.
@@ -101,7 +103,7 @@
       'name': name ?? '',
       'suiteID': suiteID ?? 0,
       'parentID': parentID,
-      'metadata': metadataJson(skip: skip),
+      'metadata': _metadataJson(skip: skip),
       'testCount': testCount ?? 1,
       'line': line,
       'column': column,
@@ -119,7 +121,7 @@
 /// [skip] is `true`, the test is expected to be marked as skipped without a
 /// reason. If it's a [String], the test is expected to be marked as skipped
 /// with that reason.
-Map<String, Object> testStartJson(int id, String name,
+Map<String, Object> testStartJson(int id, Object /*String|Matcher*/ name,
     {int? suiteID,
     Iterable<int>? groupIDs,
     int? line,
@@ -136,58 +138,43 @@
 
   url ??=
       line == null ? null : p.toUri(p.join(d.sandbox, 'test.dart')).toString();
-  var expected = {
+  return {
     'type': 'testStart',
     'test': {
       'id': id,
       'name': name,
       'suiteID': suiteID ?? 0,
       'groupIDs': groupIDs ?? [2],
-      'metadata': metadataJson(skip: skip),
+      'metadata': _metadataJson(skip: skip),
       'line': line,
       'column': column,
       'url': url,
+      if (rootLine != null) 'root_line': rootLine,
+      if (rootColumn != null) 'root_column': rootColumn,
+      if (rootUrl != null) 'root_url': rootUrl,
     }
   };
-  var testObj = expected['test'] as Map<String, dynamic>;
-  if (rootLine != null) {
-    testObj['root_line'] = rootLine;
-  }
-  if (rootColumn != null) {
-    testObj['root_column'] = rootColumn;
-  }
-  if (rootUrl != null) {
-    testObj['root_url'] = rootUrl;
-  }
-  return expected;
 }
 
 /// Returns the event emitted by the JSON reporter indicating that a test
 /// printed [message].
 Matcher printJson(int id, dynamic /*String|Matcher*/ message,
-    {String type = 'print'}) {
-  return allOf(
-    hasLength(4),
-    containsPair('type', 'print'),
-    containsPair('testID', id),
-    containsPair('message', message),
-    containsPair('messageType', type),
-  );
-}
+        {String type = 'print'}) =>
+    allOf(
+      hasLength(4),
+      containsPair('type', 'print'),
+      containsPair('testID', id),
+      containsPair('message', message),
+      containsPair('messageType', type),
+    );
 
 /// Returns the event emitted by the JSON reporter indicating that a test
 /// emitted [error].
 ///
 /// The [isFailure] parameter indicates whether the error was a [TestFailure] or
 /// not.
-Map<String, Object> errorJson(int id, String error, {bool isFailure = false}) {
-  return {
-    'type': 'error',
-    'testID': id,
-    'error': error,
-    'isFailure': isFailure
-  };
-}
+Map<String, Object> errorJson(int id, String error, {bool isFailure = false}) =>
+    {'type': 'error', 'testID': id, 'error': error, 'isFailure': isFailure};
 
 /// Returns the event emitted by the JSON reporter indicating that a test
 /// finished.
@@ -199,15 +186,16 @@
 /// after finishing. The [skipped] parameter indicates whether the test was
 /// skipped.
 Map<String, Object> testDoneJson(int id,
-    {String result = 'success', bool hidden = false, bool skipped = false}) {
-  return {
-    'type': 'testDone',
-    'testID': id,
-    'result': result,
-    'hidden': hidden,
-    'skipped': skipped
-  };
-}
+        {String result = 'success',
+        bool hidden = false,
+        bool skipped = false}) =>
+    {
+      'type': 'testDone',
+      'testID': id,
+      'result': result,
+      'hidden': hidden,
+      'skipped': skipped
+    };
 
 /// Returns the event emitted by the JSON reporter indicating that the entire
 /// run finished.
@@ -215,12 +203,7 @@
     {'type': 'done', 'success': success};
 
 /// Returns the serialized metadata corresponding to [skip].
-Map<String, Object?> metadataJson({skip}) {
-  if (skip == true) {
-    return {'skip': true, 'skipReason': null};
-  } else if (skip is String) {
-    return {'skip': true, 'skipReason': skip};
-  } else {
-    return {'skip': false, 'skipReason': null};
-  }
-}
+Map<String, Object?> _metadataJson({Object? skip}) => {
+      'skip': skip == true || skip is String,
+      'skipReason': skip is String ? skip : null
+    };
diff --git a/pkgs/test/test/runner/line_and_col_test.dart b/pkgs/test/test/runner/line_and_col_test.dart
index a973dc6..c513cef 100644
--- a/pkgs/test/test/runner/line_and_col_test.dart
+++ b/pkgs/test/test/runner/line_and_col_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_core/src/util/exit_codes.dart' as exit_codes;
diff --git a/pkgs/test/test/runner/load_suite_test.dart b/pkgs/test/test/runner/load_suite_test.dart
index 3f328a0..aa35d38 100644
--- a/pkgs/test/test/runner/load_suite_test.dart
+++ b/pkgs/test/test/runner/load_suite_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:async';
 
 import 'package:test/test.dart';
diff --git a/pkgs/test/test/runner/loader_test.dart b/pkgs/test/test/runner/loader_test.dart
index b6143b8..8d1d4ad 100644
--- a/pkgs/test/test/runner/loader_test.dart
+++ b/pkgs/test/test/runner/loader_test.dart
@@ -3,13 +3,18 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:async';
 
 import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
+import 'package:test_api/src/backend/compiler.dart';
 import 'package:test_api/src/backend/runtime.dart';
 import 'package:test_api/src/backend/state.dart';
 import 'package:test_api/src/backend/test.dart';
+import 'package:test_core/src/runner/compiler_selection.dart';
+import 'package:test_core/src/runner/load_suite.dart';
 import 'package:test_core/src/runner/loader.dart';
 import 'package:test_core/src/runner/runner_suite.dart';
 import 'package:test_core/src/runner/runner_test.dart';
@@ -41,44 +46,138 @@
 
   group('.loadFile()', () {
     late RunnerSuite suite;
-    setUp(() async {
-      await d.file('a_test.dart', _tests).create();
-      var suites = await _loader
-          .loadFile(p.join(d.sandbox, 'a_test.dart'), SuiteConfiguration.empty)
-          .toList();
-      expect(suites, hasLength(1));
-      var loadSuite = suites.first;
-      suite = (await loadSuite.getSuite())!;
+    group('with empty configuration', () {
+      setUp(() async {
+        await d.file('a_test.dart', _tests).create();
+        var suites = await _loader
+            .loadFile(
+                p.join(d.sandbox, 'a_test.dart'), SuiteConfiguration.empty)
+            .toList();
+        expect(suites, hasLength(1));
+        var loadSuite = suites.first;
+        suite = (await loadSuite.getSuite())!;
+      });
+
+      test('returns a suite with the file path and platform', () {
+        expect(suite.path, equals(p.join(d.sandbox, 'a_test.dart')));
+        expect(suite.platform.runtime, equals(Runtime.vm));
+        expect(suite.platform.compiler, equals(Runtime.vm.defaultCompiler));
+      });
+
+      test('returns entries with the correct names and platforms', () {
+        expect(suite.group.entries, hasLength(3));
+        expect(suite.group.entries[0].name, equals('success'));
+        expect(suite.group.entries[1].name, equals('failure'));
+        expect(suite.group.entries[2].name, equals('error'));
+      });
+
+      test('can load and run a successful test', () {
+        var liveTest = (suite.group.entries[0] as RunnerTest).load(suite);
+
+        expectStates(liveTest, [
+          const State(Status.running, Result.success),
+          const State(Status.complete, Result.success)
+        ]);
+        expectErrors(liveTest, []);
+
+        return liveTest.run().whenComplete(() => liveTest.close());
+      });
+
+      test('can load and run a failing test', () {
+        var liveTest = (suite.group.entries[1] as RunnerTest).load(suite);
+        expectSingleFailure(liveTest);
+        return liveTest.run().whenComplete(() => liveTest.close());
+      });
     });
 
-    test('returns a suite with the file path and platform', () {
-      expect(suite.path, equals(p.join(d.sandbox, 'a_test.dart')));
-      expect(suite.platform.runtime, equals(Runtime.vm));
-    });
+    group('with compiler selection', () {
+      Future<List<LoadSuite>> loadSuitesWithConfig(
+          SuiteConfiguration suiteConfiguration) async {
+        await d.file('a_test.dart', _tests).create();
+        return _loader
+            .loadFile(p.join(d.sandbox, 'a_test.dart'), suiteConfiguration)
+            .toList();
+      }
 
-    test('returns entries with the correct names and platforms', () {
-      expect(suite.group.entries, hasLength(3));
-      expect(suite.group.entries[0].name, equals('success'));
-      expect(suite.group.entries[1].name, equals('failure'));
-      expect(suite.group.entries[2].name, equals('error'));
-    });
+      test('with a single compiler selection, uses the selected compiler',
+          () async {
+        var suites = await loadSuitesWithConfig(suiteConfiguration(
+            compilerSelections: [CompilerSelection.parse('source')]));
+        expect(suites, hasLength(1));
+        var loadSuite = suites.first;
+        suite = (await loadSuite.getSuite())!;
+        expect(suite.path, equals(p.join(d.sandbox, 'a_test.dart')));
+        expect(suite.platform.runtime, equals(Runtime.vm));
+        expect(suite.platform.compiler, equals(Compiler.source));
+      });
 
-    test('can load and run a successful test', () {
-      var liveTest = (suite.group.entries[0] as RunnerTest).load(suite);
+      test('with multiple compiler selections, returns a suite for each',
+          () async {
+        var suites = await loadSuitesWithConfig(suiteConfiguration(
+            compilerSelections: [
+              CompilerSelection.parse('source'),
+              CompilerSelection.parse('kernel')
+            ]));
 
-      expectStates(liveTest, [
-        const State(Status.running, Result.success),
-        const State(Status.complete, Result.success)
-      ]);
-      expectErrors(liveTest, []);
+        expect(suites, hasLength(2));
+        var runnerSuites =
+            await Future.wait([for (var suite in suites) suite.getSuite()]);
+        expect(
+            runnerSuites,
+            unorderedEquals([
+              isA<RunnerSuite>()
+                  .having(
+                      (s) => s.platform.runtime, 'The vm runtime', Runtime.vm)
+                  .having((s) => s.platform.compiler, 'The source compiler',
+                      Compiler.source),
+              isA<RunnerSuite>()
+                  .having(
+                      (s) => s.platform.runtime, 'The vm runtime', Runtime.vm)
+                  .having((s) => s.platform.compiler, 'The kernel compiler',
+                      Compiler.kernel),
+            ]));
+      });
 
-      return liveTest.run().whenComplete(() => liveTest.close());
-    });
+      test('with unsupported compiler selections, uses the default compiler',
+          () async {
+        var suites =
+            await loadSuitesWithConfig(suiteConfiguration(compilerSelections: [
+          CompilerSelection.parse('dart2js'),
+        ]));
+        expect(suites, hasLength(1));
+        var loadSuite = suites.first;
+        suite = (await loadSuite.getSuite())!;
+        expect(suite.path, equals(p.join(d.sandbox, 'a_test.dart')));
+        expect(suite.platform.runtime, equals(Runtime.vm));
+        expect(suite.platform.compiler, equals(Runtime.vm.defaultCompiler));
+      });
 
-    test('can load and run a failing test', () {
-      var liveTest = (suite.group.entries[1] as RunnerTest).load(suite);
-      expectSingleFailure(liveTest);
-      return liveTest.run().whenComplete(() => liveTest.close());
+      test('compiler selections support matching boolean selectors', () async {
+        var suites =
+            await loadSuitesWithConfig(suiteConfiguration(compilerSelections: [
+          CompilerSelection.parse('vm:source'),
+        ]));
+        expect(suites, hasLength(1));
+        var loadSuite = suites.first;
+        suite = (await loadSuite.getSuite())!;
+        expect(suite.path, equals(p.join(d.sandbox, 'a_test.dart')));
+        expect(suite.platform.runtime, equals(Runtime.vm));
+        expect(suite.platform.compiler, equals(Compiler.source));
+      });
+
+      test('compiler selections support unmatched boolean selectors', () async {
+        var suites =
+            await loadSuitesWithConfig(suiteConfiguration(compilerSelections: [
+          CompilerSelection.parse('browser:source'),
+        ]));
+        expect(suites, hasLength(1));
+        var loadSuite = suites.first;
+        suite = (await loadSuite.getSuite())!;
+        expect(suite.path, equals(p.join(d.sandbox, 'a_test.dart')));
+        expect(suite.platform.runtime, equals(Runtime.vm));
+        expect(suite.platform.compiler,
+            allOf(Runtime.vm.defaultCompiler, isNot(Compiler.source)));
+      });
     });
   });
 
diff --git a/pkgs/test/test/runner/name_test.dart b/pkgs/test/test/runner/name_test.dart
index ed539d5..bd4dc21 100644
--- a/pkgs/test/test/runner/name_test.dart
+++ b/pkgs/test/test/runner/name_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_core/src/util/exit_codes.dart' as exit_codes;
diff --git a/pkgs/test/test/runner/node/runner_test.dart b/pkgs/test/test/runner/node/runner_test.dart
index 522acd7..aba2604 100644
--- a/pkgs/test/test/runner/node/runner_test.dart
+++ b/pkgs/test/test/runner/node/runner_test.dart
@@ -4,6 +4,7 @@
 
 @TestOn('vm')
 @Tags(['node'])
+library;
 
 import 'package:test/test.dart';
 import 'package:test_core/src/util/io.dart';
@@ -39,7 +40,7 @@
           test.stdout,
           containsInOrder([
             'Error: Compilation failed.',
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": dart2js failed.'
           ]));
       await test.shouldExit(1);
@@ -52,7 +53,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": oh no'
           ]));
       await test.shouldExit(1);
@@ -65,7 +66,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": No top-level main() function defined.'
           ]));
       await test.shouldExit(1);
@@ -78,7 +79,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": Top-level main getter is not a function.'
           ]));
       await test.shouldExit(1);
@@ -91,7 +92,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling test.dart [E]',
+            '-1: loading test.dart [E]',
             'Failed to load "test.dart": Top-level main() function takes arguments.'
           ]));
       await test.shouldExit(1);
diff --git a/pkgs/test/test/runner/parse_metadata_test.dart b/pkgs/test/test/runner/parse_metadata_test.dart
index 635d881..5fb7434 100644
--- a/pkgs/test/test/runner/parse_metadata_test.dart
+++ b/pkgs/test/test/runner/parse_metadata_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'package:test/test.dart';
 import 'package:test_api/src/backend/platform_selector.dart';
 import 'package:test_api/src/backend/runtime.dart';
@@ -30,15 +32,23 @@
         "@foo.TestOn('vm')\n"
         "import 'package:test/test.dart' as foo;",
         {});
-    expect(metadata.testOn.evaluate(SuitePlatform(Runtime.vm)), isTrue);
-    expect(metadata.testOn.evaluate(SuitePlatform(Runtime.chrome)), isFalse);
+    expect(metadata.testOn.evaluate(SuitePlatform(Runtime.vm, compiler: null)),
+        isTrue);
+    expect(
+        metadata.testOn.evaluate(SuitePlatform(Runtime.chrome, compiler: null)),
+        isFalse);
   });
 
   group('@TestOn:', () {
     test('parses a valid annotation', () {
       var metadata = parseMetadata(_path, "@TestOn('vm')\nlibrary foo;", {});
-      expect(metadata.testOn.evaluate(SuitePlatform(Runtime.vm)), isTrue);
-      expect(metadata.testOn.evaluate(SuitePlatform(Runtime.chrome)), isFalse);
+      expect(
+          metadata.testOn.evaluate(SuitePlatform(Runtime.vm, compiler: null)),
+          isTrue);
+      expect(
+          metadata.testOn
+              .evaluate(SuitePlatform(Runtime.chrome, compiler: null)),
+          isFalse);
     });
 
     test('ignores a constructor named TestOn', () {
@@ -237,14 +247,16 @@
 library foo;''', {});
 
       var key = metadata.onPlatform.keys.first;
-      expect(key.evaluate(SuitePlatform(Runtime.chrome)), isTrue);
-      expect(key.evaluate(SuitePlatform(Runtime.vm)), isFalse);
+      expect(
+          key.evaluate(SuitePlatform(Runtime.chrome, compiler: null)), isTrue);
+      expect(key.evaluate(SuitePlatform(Runtime.vm, compiler: null)), isFalse);
       var value = metadata.onPlatform.values.first;
       expect(value.timeout.scaleFactor, equals(2));
 
       key = metadata.onPlatform.keys.last;
-      expect(key.evaluate(SuitePlatform(Runtime.vm)), isTrue);
-      expect(key.evaluate(SuitePlatform(Runtime.chrome)), isFalse);
+      expect(key.evaluate(SuitePlatform(Runtime.vm, compiler: null)), isTrue);
+      expect(
+          key.evaluate(SuitePlatform(Runtime.chrome, compiler: null)), isFalse);
       value = metadata.onPlatform.values.last;
       expect(value.skip, isTrue);
       expect(value.timeout.scaleFactor, equals(3));
@@ -260,14 +272,16 @@
 ''', {});
 
       var key = metadata.onPlatform.keys.first;
-      expect(key.evaluate(SuitePlatform(Runtime.chrome)), isTrue);
-      expect(key.evaluate(SuitePlatform(Runtime.vm)), isFalse);
+      expect(
+          key.evaluate(SuitePlatform(Runtime.chrome, compiler: null)), isTrue);
+      expect(key.evaluate(SuitePlatform(Runtime.vm, compiler: null)), isFalse);
       var value = metadata.onPlatform.values.first;
       expect(value.timeout.scaleFactor, equals(2));
 
       key = metadata.onPlatform.keys.last;
-      expect(key.evaluate(SuitePlatform(Runtime.vm)), isTrue);
-      expect(key.evaluate(SuitePlatform(Runtime.chrome)), isFalse);
+      expect(key.evaluate(SuitePlatform(Runtime.vm, compiler: null)), isTrue);
+      expect(
+          key.evaluate(SuitePlatform(Runtime.chrome, compiler: null)), isFalse);
       value = metadata.onPlatform.values.last;
       expect(value.skip, isTrue);
       expect(value.timeout.scaleFactor, equals(3));
diff --git a/pkgs/test/test/runner/pause_after_load_test.dart b/pkgs/test/test/runner/pause_after_load_test.dart
index 8b48b2d..691a86d 100644
--- a/pkgs/test/test/runner/pause_after_load_test.dart
+++ b/pkgs/test/test/runner/pause_after_load_test.dart
@@ -4,6 +4,7 @@
 
 @TestOn('vm')
 @OnPlatform({'windows': Skip('https://github.com/dart-lang/test/issues/1613')})
+library;
 
 import 'dart:async';
 import 'dart:io';
@@ -115,7 +116,7 @@
 
     var nextLineFired = false;
     unawaited(test.stdout.next.then(expectAsync1((line) {
-      expect(line, contains('+0: [Firefox] success'));
+      expect(line, contains('+0: [Firefox, Dart2Js] success'));
       nextLineFired = true;
     })));
 
@@ -137,7 +138,7 @@
 
     nextLineFired = false;
     unawaited(test.stdout.next.then(expectAsync1((line) {
-      expect(line, contains('+1: [Chrome] success'));
+      expect(line, contains('+1: [Chrome, Dart2Js] success'));
       nextLineFired = true;
     })));
 
@@ -158,7 +159,7 @@
 
     nextLineFired = false;
     unawaited(test.stdout.next.then(expectAsync1((line) {
-      expect(line, contains('+2: [VM] success'));
+      expect(line, contains('+2: [VM, Kernel] success'));
       nextLineFired = true;
     })));
 
diff --git a/pkgs/test/test/runner/precompiled_test.dart b/pkgs/test/test/runner/precompiled_test.dart
index 25bfac1..181d68f 100644
--- a/pkgs/test/test/runner/precompiled_test.dart
+++ b/pkgs/test/test/runner/precompiled_test.dart
@@ -4,6 +4,7 @@
 
 @TestOn('vm')
 @OnPlatform({'windows': Skip('https://github.com/dart-lang/test/issues/1617')})
+library;
 
 import 'dart:async';
 import 'dart:io';
diff --git a/pkgs/test/test/runner/pub_serve_test.dart b/pkgs/test/test/runner/pub_serve_test.dart
index 8c33699..8a0b2b2 100644
--- a/pkgs/test/test/runner/pub_serve_test.dart
+++ b/pkgs/test/test/runner/pub_serve_test.dart
@@ -5,6 +5,7 @@
 @TestOn('vm')
 @Tags(['pub'])
 @Skip('https://github.com/dart-lang/test/issues/821')
+library;
 
 import 'dart:io';
 
@@ -131,7 +132,7 @@
         expect(
             test.stdout,
             containsInOrder([
-              '-1: compiling ${p.join("test", "my_test.dart")} [E]',
+              '-1: loading ${p.join("test", "my_test.dart")} [E]',
               'Failed to load "${p.join("test", "my_test.dart")}":',
               '404 Not Found',
               'Make sure "pub serve" is serving the test/ directory.'
@@ -152,7 +153,7 @@
       expect(
           test.stdout,
           containsInOrder([
-            '-1: compiling ${p.join("test", "my_test.dart")} [E]',
+            '-1: loading ${p.join("test", "my_test.dart")} [E]',
             'Failed to load "${p.join("test", "my_test.dart")}":',
             '404 Not Found',
             'Make sure "pub serve" is serving the test/ directory.'
@@ -293,7 +294,7 @@
     expect(
         test.stdout,
         containsInOrder([
-          '-1: compiling ${p.join("test", "my_test.dart")} [E]',
+          '-1: loading ${p.join("test", "my_test.dart")} [E]',
           'Failed to load "${p.join("test", "my_test.dart")}":',
           'Error getting http://localhost:54321/my_test.dart.browser_test.dart.js'
               '.map: $message',
@@ -311,7 +312,7 @@
     expect(
         test.stdout,
         containsInOrder([
-          '-1: compiling ${p.join("test", "my_test.dart")} [E]',
+          '-1: loading ${p.join("test", "my_test.dart")} [E]',
           'Failed to load "${p.join("test", "my_test.dart")}":',
           'Error getting http://localhost:54321/my_test.dart.node_test.dart.js:'
               ' $message',
@@ -344,7 +345,7 @@
 /// as the first argument.
 void testWithCompiler(
     String name, dynamic Function(List<String> compilerArgs) testFn,
-    {tags}) {
+    {Object? tags}) {
   for (var compiler in _compilers) {
     var compilerArgs = ['--web-compiler', compiler];
     test('$name with $compiler', () => testFn(compilerArgs), tags: tags);
diff --git a/pkgs/test/test/runner/retry_test.dart b/pkgs/test/test/runner/retry_test.dart
index c45fbb5..0e16fef 100644
--- a/pkgs/test/test/runner/retry_test.dart
+++ b/pkgs/test/test/runner/retry_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
diff --git a/pkgs/test/test/runner/runner_test.dart b/pkgs/test/test/runner/runner_test.dart
index 19419af..6d9a2ff 100644
--- a/pkgs/test/test/runner/runner_test.dart
+++ b/pkgs/test/test/runner/runner_test.dart
@@ -3,10 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:io';
 import 'dart:math' as math;
 
+import 'package:path/path.dart' as p;
 import 'package:test/test.dart';
 import 'package:test_core/src/util/exit_codes.dart' as exit_codes;
 import 'package:test_descriptor/test_descriptor.dart' as d;
@@ -69,7 +71,13 @@
 
 Running Tests:
 -p, --platform                        The platform(s) on which to run the tests.
-                                      $_runtimes
+                                      $_runtimes.
+                                      Each platform supports the following compilers:
+$_runtimeCompilers
+-c, --compiler                        The compiler(s) to use to run tests, supported compilers are [dart2js, dart2wasm, exe, kernel, source].
+                                      Each platform has a default compiler but may support other compilers.
+                                      You can target a compiler to a specific platform using arguments of the following form [<platform-selector>:]<compiler>.
+                                      If a platform is specified but no given compiler is supported for that platform, then it will use its default compiler.
 -P, --preset                          The configuration preset(s) to use.
 -j, --concurrency=<threads>           The number of concurrent test suites run.
                                       (defaults to "$_defaultConcurrency")
@@ -90,13 +98,11 @@
                                       to provide improved test performance but at the cost of
                                       debuggability.
     --no-retry                        Don't rerun tests that have retry set.
-    --use-data-isolate-strategy       Use `data:` uri isolates when spawning VM tests instead of the
-                                      default strategy. This may be faster when you only ever run a
-                                      single test suite at a time.
     --test-randomize-ordering-seed    Use the specified seed to randomize the execution order of test cases.
                                       Must be a 32bit unsigned integer or "random".
                                       If "random", pick a random seed to use.
                                       If not passed, do not randomize test case execution order.
+    --[no-]fail-fast                  Stop running tests after the first failure.
 
 Output:
 -r, --reporter=<option>               Set how to print test results.
@@ -112,14 +118,24 @@
     --js-trace                        Emit raw JavaScript stack traces for browser tests.
     --[no-]color                      Use terminal colors.
                                       (auto-detected by default)
-
 ''';
 
 final _runtimes = '[vm (default), chrome, firefox'
     '${Platform.isMacOS ? ', safari' : ''}'
-    '${Platform.isWindows ? ', ie' : ''}, node, '
+    '${Platform.isWindows ? ', ie' : ''}, edge, node, '
     'experimental-chrome-wasm]';
 
+final _runtimeCompilers = [
+  '[vm]: kernel (default), source, exe',
+  '[chrome]: dart2js (default)',
+  '[firefox]: dart2js (default)',
+  if (Platform.isMacOS) '[safari]: dart2js (default)',
+  if (Platform.isWindows) '[ie]: dart2js (default)',
+  '[edge]: dart2js (default)',
+  '[node]: dart2js (default)',
+  '[experimental-chrome-wasm]: dart2wasm (default)',
+].map((str) => '                                      $str').join('\n');
+
 void main() {
   setUpAll(precompileTestExecutable);
 
@@ -362,6 +378,37 @@
       expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
       await test.shouldExit(0);
     });
+
+    test('given a file: uri', () async {
+      await d.file('test.dart', _success).create();
+      var fileUri = p.toUri(d.path('test.dart')).toString();
+      expect(fileUri, startsWith('file:///'));
+      var test = await runTest([fileUri]);
+      expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
+      await test.shouldExit(0);
+    });
+
+    test('with platform specific relative paths', () async {
+      await d.dir('foo', [d.file('test.dart', _success)]).create();
+      var test = await runTest([p.join('foo', 'test.dart')]);
+      expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
+      await test.shouldExit(0);
+    });
+
+    test('with platform specific absolute paths', () async {
+      await d.dir('foo', [d.file('test.dart', _success)]).create();
+      var test = await runTest([d.path(p.join('foo', 'test.dart'))]);
+      expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
+      await test.shouldExit(0);
+    });
+
+    test('with platform specific relative paths containing query params',
+        () async {
+      await d.dir('foo', [d.file('test.dart', _success)]).create();
+      var test = await runTest(['${p.join('foo', 'test.dart')}?line=6']);
+      expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
+      await test.shouldExit(0);
+    });
   });
 
   group('runs successful tests with async setup', () {
diff --git a/pkgs/test/test/runner/set_up_all_test.dart b/pkgs/test/test/runner/set_up_all_test.dart
index bcad996..d1259e1 100644
--- a/pkgs/test/test/runner/set_up_all_test.dart
+++ b/pkgs/test/test/runner/set_up_all_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
diff --git a/pkgs/test/test/runner/shard_test.dart b/pkgs/test/test/runner/shard_test.dart
index 0d1f72b..8d4be86 100644
--- a/pkgs/test/test/runner/shard_test.dart
+++ b/pkgs/test/test/runner/shard_test.dart
@@ -3,8 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
-
-import 'dart:io';
+library;
 
 import 'package:test/test.dart';
 import 'package:test_core/src/util/exit_codes.dart' as exit_codes;
@@ -95,14 +94,10 @@
         test.stdout,
         emitsInOrder([
           emitsAnyOf([
-            containsInOrder([
-              '+0: .${Platform.pathSeparator}1_test.dart: test 1.1',
-              '+1: .${Platform.pathSeparator}2_test.dart: test 2.1'
-            ]),
-            containsInOrder([
-              '+0: .${Platform.pathSeparator}2_test.dart: test 2.1',
-              '+1: .${Platform.pathSeparator}1_test.dart: test 1.1'
-            ])
+            containsInOrder(
+                ['+0: ./1_test.dart: test 1.1', '+1: ./2_test.dart: test 2.1']),
+            containsInOrder(
+                ['+0: ./2_test.dart: test 2.1', '+1: ./1_test.dart: test 1.1'])
           ]),
           contains('+2: All tests passed!')
         ]));
@@ -113,14 +108,10 @@
         test.stdout,
         emitsInOrder([
           emitsAnyOf([
-            containsInOrder([
-              '+0: .${Platform.pathSeparator}1_test.dart: test 1.2',
-              '+1: .${Platform.pathSeparator}2_test.dart: test 2.2'
-            ]),
-            containsInOrder([
-              '+0: .${Platform.pathSeparator}2_test.dart: test 2.2',
-              '+1: .${Platform.pathSeparator}1_test.dart: test 1.2'
-            ])
+            containsInOrder(
+                ['+0: ./1_test.dart: test 1.2', '+1: ./2_test.dart: test 2.2']),
+            containsInOrder(
+                ['+0: ./2_test.dart: test 2.2', '+1: ./1_test.dart: test 1.2'])
           ]),
           contains('+2: All tests passed!')
         ]));
@@ -131,14 +122,10 @@
         test.stdout,
         emitsInOrder([
           emitsAnyOf([
-            containsInOrder([
-              '+0: .${Platform.pathSeparator}1_test.dart: test 1.3',
-              '+1: .${Platform.pathSeparator}2_test.dart: test 2.3'
-            ]),
-            containsInOrder([
-              '+0: .${Platform.pathSeparator}2_test.dart: test 2.3',
-              '+1: .${Platform.pathSeparator}1_test.dart: test 1.3'
-            ])
+            containsInOrder(
+                ['+0: ./1_test.dart: test 1.3', '+1: ./2_test.dart: test 2.3']),
+            containsInOrder(
+                ['+0: ./2_test.dart: test 2.3', '+1: ./1_test.dart: test 1.3'])
           ]),
           contains('+2: All tests passed!')
         ]));
diff --git a/pkgs/test/test/runner/signal_test.dart b/pkgs/test/test/runner/signal_test.dart
index 861ce9c..8a093d9 100644
--- a/pkgs/test/test/runner/signal_test.dart
+++ b/pkgs/test/test/runner/signal_test.dart
@@ -4,6 +4,7 @@
 
 // Windows doesn't support sending signals.
 @TestOn('vm && !windows')
+library;
 
 import 'dart:async';
 import 'dart:io';
@@ -48,7 +49,7 @@
 
       var test = await _runTest(['-p', 'chrome', 'test.dart']);
       await expectLater(
-          test.stdout, emitsThrough(endsWith('compiling test.dart')));
+          test.stdout, emitsThrough(endsWith('loading test.dart')));
       await signalAndQuit(test);
 
       expectTempDirEmpty(skip: 'Failing on Travis.');
@@ -230,6 +231,6 @@
   await expectLater(test.stderr, emitsDone);
 }
 
-void expectTempDirEmpty({skip}) {
+void expectTempDirEmpty({Object? skip}) {
   expect(Directory(_tempDir).listSync(), isEmpty, skip: skip);
 }
diff --git a/pkgs/test/test/runner/skip_expect_test.dart b/pkgs/test/test/runner/skip_expect_test.dart
index 97e1330..e22332c 100644
--- a/pkgs/test/test/runner/skip_expect_test.dart
+++ b/pkgs/test/test/runner/skip_expect_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
@@ -197,9 +198,9 @@
             '+0: skip',
             '+1: wait',
             '+0 -1: skip',
-            'This test was marked as skipped after it had already completed. '
-                'Make sure to use',
-            '[expectAsync] or the [completes] matcher when testing async code.',
+            'This test was marked as skipped after it had already completed.',
+            'Make sure to use a matching library which informs the test runner',
+            'of pending async work.',
             '+1 -1: Some tests failed.'
           ]));
       await test.shouldExit(1);
@@ -239,9 +240,9 @@
             '+0: skip',
             '+1: wait',
             '+0 -1: skip',
-            'This test was marked as skipped after it had already completed. '
-                'Make sure to use',
-            '[expectAsync] or the [completes] matcher when testing async code.',
+            'This test was marked as skipped after it had already completed.',
+            'Make sure to use a matching library which informs the test runner',
+            'of pending async work.',
             '+1 -1: Some tests failed.'
           ]));
       await test.shouldExit(1);
diff --git a/pkgs/test/test/runner/solo_test.dart b/pkgs/test/test/runner/solo_test.dart
index 508ac67..87f6f25 100644
--- a/pkgs/test/test/runner/solo_test.dart
+++ b/pkgs/test/test/runner/solo_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
diff --git a/pkgs/test/test/runner/tag_test.dart b/pkgs/test/test/runner/tag_test.dart
index 129358c..da9dca7 100644
--- a/pkgs/test/test/runner/tag_test.dart
+++ b/pkgs/test/test/runner/tag_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
 
diff --git a/pkgs/test/test/runner/tear_down_all_test.dart b/pkgs/test/test/runner/tear_down_all_test.dart
index 3af6e56..93ede4f 100644
--- a/pkgs/test/test/runner/tear_down_all_test.dart
+++ b/pkgs/test/test/runner/tear_down_all_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
diff --git a/pkgs/test/test/runner/test_chain_test.dart b/pkgs/test/test/runner/test_chain_test.dart
index e7c1da0..ad814de 100644
--- a/pkgs/test/test/runner/test_chain_test.dart
+++ b/pkgs/test/test/runner/test_chain_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:convert';
 
diff --git a/pkgs/test/test/runner/test_on_test.dart b/pkgs/test/test/runner/test_on_test.dart
index d9ca7bf..96baf0b 100644
--- a/pkgs/test/test/runner/test_on_test.dart
+++ b/pkgs/test/test/runner/test_on_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:async';
 import 'dart:convert';
diff --git a/pkgs/test/test/runner/timeout_test.dart b/pkgs/test/test/runner/timeout_test.dart
index aa4764c..6f4b0e7 100644
--- a/pkgs/test/test/runner/timeout_test.dart
+++ b/pkgs/test/test/runner/timeout_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'package:test/test.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
diff --git a/pkgs/test/test/util/string_literal_iterator_test.dart b/pkgs/test/test/util/string_literal_iterator_test.dart
index 4bb5aa0..03c8e34 100644
--- a/pkgs/test/test/util/string_literal_iterator_test.dart
+++ b/pkgs/test/test/util/string_literal_iterator_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'package:analyzer/dart/analysis/utilities.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:test/test.dart';
diff --git a/pkgs/test/test/utils.dart b/pkgs/test/test/utils.dart
index 52b4e4c..52c708d 100644
--- a/pkgs/test/test/utils.dart
+++ b/pkgs/test/test/utils.dart
@@ -20,6 +20,7 @@
 import 'package:test_api/src/backend/suite.dart';
 import 'package:test_api/src/backend/suite_platform.dart';
 import 'package:test_core/src/runner/application_exception.dart';
+import 'package:test_core/src/runner/compiler_selection.dart';
 import 'package:test_core/src/runner/configuration.dart';
 import 'package:test_core/src/runner/configuration/custom_runtime.dart';
 import 'package:test_core/src/runner/configuration/runtime_settings.dart';
@@ -31,7 +32,7 @@
 import 'package:test_core/src/runner/suite.dart';
 
 /// A dummy suite platform to use for testing suites.
-final suitePlatform = SuitePlatform(Runtime.vm);
+final suitePlatform = SuitePlatform(Runtime.vm, compiler: null);
 
 // The last state change detected via [expectStates].
 State? lastState;
@@ -90,19 +91,19 @@
 /// [TestFailure] with the given [message].
 ///
 /// [message] can be a string or a [Matcher].
-Matcher throwsTestFailure(message) => throwsA(isTestFailure(message));
+Matcher throwsTestFailure(Object message) => throwsA(isTestFailure(message));
 
 /// Returns a matcher that matches a [TestFailure] with the given [message].
 ///
 /// [message] can be a string or a [Matcher].
-Matcher isTestFailure(message) => const TypeMatcher<TestFailure>()
+Matcher isTestFailure(Object message) => const TypeMatcher<TestFailure>()
     .having((e) => e.message, 'message', message);
 
 /// Returns a matcher that matches a [ApplicationException] with the given
 /// [message].
 ///
 /// [message] can be a string or a [Matcher].
-Matcher isApplicationException(message) =>
+Matcher isApplicationException(Object message) =>
     const TypeMatcher<ApplicationException>()
         .having((e) => e.message, 'message', message);
 
@@ -141,7 +142,7 @@
 
 /// Asserts that [liveTest] failed with a single [TestFailure] whose message
 /// matches [message].
-void expectTestFailed(LiveTest liveTest, message) {
+void expectTestFailed(LiveTest liveTest, Object message) {
   expect(liveTest.state.status, equals(Status.complete));
   expect(liveTest.state.result, equals(Result.failure));
   expect(liveTest.errors, hasLength(1));
@@ -194,16 +195,24 @@
 }
 
 /// Runs [body] with a declarer and returns an engine that runs those tests.
-Engine declareEngine(void Function() body,
-    {bool runSkipped = false, String? coverage}) {
+Engine declareEngine(
+  void Function() body, {
+  bool runSkipped = false,
+  String? coverage,
+  bool stopOnFirstFailure = false,
+}) {
   var declarer = Declarer()..declare(body);
-  return Engine.withSuites([
-    RunnerSuite(
-        const PluginEnvironment(),
-        SuiteConfiguration.runSkipped(runSkipped),
-        declarer.build(),
-        suitePlatform)
-  ], coverage: coverage);
+  return Engine.withSuites(
+    [
+      RunnerSuite(
+          const PluginEnvironment(),
+          SuiteConfiguration.runSkipped(runSkipped),
+          declarer.build(),
+          suitePlatform)
+    ],
+    coverage: coverage,
+    stopOnFirstFailure: stopOnFirstFailure,
+  );
 }
 
 /// Returns a [RunnerSuite] with a default environment and configuration.
@@ -221,6 +230,7 @@
         bool? runSkipped,
         Iterable<String>? dart2jsArgs,
         String? precompiledPath,
+        Iterable<CompilerSelection>? compilerSelections,
         Iterable<RuntimeSelection>? runtimes,
         Map<BooleanSelector, SuiteConfiguration>? tags,
         Map<PlatformSelector, SuiteConfiguration>? onPlatform,
@@ -242,6 +252,7 @@
         runSkipped: runSkipped,
         dart2jsArgs: dart2jsArgs,
         precompiledPath: precompiledPath,
+        compilerSelections: compilerSelections,
         runtimes: runtimes,
         tags: tags,
         onPlatform: onPlatform,
@@ -279,7 +290,6 @@
         Map<String, RuntimeSettings>? overrideRuntimes,
         Map<String, CustomRuntime>? defineRuntimes,
         bool? noRetry,
-        bool? useDataIsolateStrategy,
         bool? ignoreTimeouts,
 
         // Suite-level configuration
@@ -290,6 +300,7 @@
         Iterable<String>? dart2jsArgs,
         String? precompiledPath,
         Iterable<Pattern>? globalPatterns,
+        Iterable<CompilerSelection>? compilerSelections,
         Iterable<RuntimeSelection>? runtimes,
         BooleanSelector? includeTags,
         BooleanSelector? excludeTags,
@@ -330,7 +341,6 @@
         overrideRuntimes: overrideRuntimes,
         defineRuntimes: defineRuntimes,
         noRetry: noRetry,
-        useDataIsolateStrategy: useDataIsolateStrategy,
         ignoreTimeouts: ignoreTimeouts,
         allowDuplicateTestNames: allowDuplicateTestNames,
         allowTestRandomization: allowTestRandomization,
@@ -339,12 +349,14 @@
         dart2jsArgs: dart2jsArgs,
         precompiledPath: precompiledPath,
         globalPatterns: globalPatterns,
+        compilerSelections: compilerSelections,
         runtimes: runtimes,
         includeTags: includeTags,
         excludeTags: excludeTags,
         tags: tags,
         onPlatform: onPlatform,
         testRandomizeOrderingSeed: testRandomizeOrderingSeed,
+        stopOnFirstFailure: false,
         timeout: timeout,
         verboseTrace: verboseTrace,
         chainStackTraces: chainStackTraces,
diff --git a/pkgs/test/tool/host.dart b/pkgs/test/tool/host.dart
index 23d83ae..8c0de4e 100644
--- a/pkgs/test/tool/host.dart
+++ b/pkgs/test/tool/host.dart
@@ -14,19 +14,6 @@
 import 'package:stream_channel/stream_channel.dart';
 import 'package:test/src/runner/browser/dom.dart' as dom;
 
-/// A class defined in content shell, used to control its behavior.
-@JS()
-@staticInterop
-class TestRunner {}
-
-extension TestRunnerExtension on TestRunner {
-  external void waitUntilDone();
-}
-
-/// Returns the current content shell runner, or `null` if none exists.
-@JS()
-external TestRunner? get testRunner;
-
 /// A class that exposes the test API to JS.
 ///
 /// These are exposed so that tools like IDEs can interact with them via remote
@@ -59,8 +46,8 @@
 final _iframes = <int, dom.HTMLIFrameElement>{};
 
 /// Subscriptions created for each loaded test suite, indexed by the suite id.
-final _subscriptions = <int, List<StreamSubscription<void>>>{};
-final _domSubscriptions = <int, List<dom.Subscription>>{};
+final _subscriptions = <int, StreamSubscription<void>>{};
+final _domSubscriptions = <int, dom.Subscription>{};
 
 /// The URL for the current page.
 final _currentUrl = Uri.parse(dom.window.location.href);
@@ -104,7 +91,7 @@
 /// connected to each test suite's iframe via a [MessageChannel].
 ///
 /// Each iframe runs a `RemoteListener` which creates its own [MultiChannel] on
-/// top of the [MessageChannel] connection. One connection is used for
+/// top of a [MessageChannel] connection. One connection is used for
 /// the `RemoteListener`, which sends messages like "here are all the tests in
 /// this suite". The rest are used for each test, receiving messages like
 /// "start running". A new connection is also created whenever a test begins
@@ -117,10 +104,6 @@
 /// does mean that the server needs to be sure to nest its [MultiChannel]s at
 /// the same place the client does.
 void main() {
-  // This tells content_shell not to close immediately after the page has
-  // rendered.
-  testRunner?.waitUntilDone();
-
   if (_currentUrl.queryParameters['debug'] == 'true') {
     dom.document.body!.classList.add('debug');
   }
@@ -130,9 +113,9 @@
     serverChannel.stream.listen((message) {
       if (message['command'] == 'loadSuite') {
         var suiteChannel =
-            serverChannel.virtualChannel(message['channel'] as int);
-        var iframeChannel =
-            _connectToIframe(message['url'] as String, message['id'] as int);
+            serverChannel.virtualChannel((message['channel'] as num).toInt());
+        var iframeChannel = _connectToIframe(
+            message['url'] as String, (message['id'] as num).toInt());
         suiteChannel.pipe(iframeChannel);
       } else if (message['command'] == 'displayPause') {
         dom.document.body!.classList.add('paused');
@@ -141,13 +124,8 @@
       } else {
         assert(message['command'] == 'closeSuite');
         _iframes.remove(message['id'])!.remove();
-
-        for (var subscription in _subscriptions.remove(message['id'])!) {
-          subscription.cancel();
-        }
-        for (var subscription in _domSubscriptions.remove(message['id'])!) {
-          subscription.cancel();
-        }
+        _subscriptions.remove(message['id'])?.cancel();
+        _domSubscriptions.remove(message['id'])?.cancel();
       }
     });
 
@@ -195,74 +173,93 @@
   return MultiChannel(controller.foreign);
 }
 
-/// Creates an iframe with `src` [url] and establishes a connection to it using
-/// a [MessageChannel].
+/// Creates an iframe with `src` [url] and expects a message back to connect a
+/// message channel with the suite running in the frame.
 ///
 /// [id] identifies the suite loaded in this iframe.
+///
+/// Before the frame is attached, adds a listener for `window.onMessage` which
+/// filters to only the messages coming from this frame (by it's URL) and
+/// expects the first message to be either an initialization message, (coming
+/// from the browser bootstrap message channel initialization), or a map with
+/// the key 'exception' set to true and details in the value for 'data' (coming
+/// from `dart.js` due to a load exception).
+///
+/// Legacy bootstrap implementations send a `{'ready': true}` message as a
+/// signal for this host to create a [MessageChannel] and send the port through
+/// the frame's `window.onMessage` channel.
+///
+/// Upcoming bootstrap implementations will send the string 'port' and include a
+/// port for a prepared [MessageChannel].
+///
+/// Returns a [StreamChannel] which will be connected to the frame once the
+/// message channel port is active.
 StreamChannel<dynamic> _connectToIframe(String url, int id) {
   var iframe = dom.createHTMLIFrameElement();
   _iframes[id] = iframe;
-  iframe.src = url;
-  dom.document.body!.appendChild(iframe);
-
-  // Use this to communicate securely with the iframe.
-  var channel = dom.createMessageChannel();
   var controller = StreamChannelController(sync: true);
 
-  // Use this to avoid sending a message to the iframe before it's sent a
-  // message to us. This ensures that no messages get dropped on the floor.
-  var readyCompleter = Completer();
-
-  var subscriptions = <StreamSubscription<void>>[];
-  var domSubscriptions = <dom.Subscription>[];
-  _subscriptions[id] = subscriptions;
-  _domSubscriptions[id] = domSubscriptions;
-
-  domSubscriptions.add(
+  late dom.Subscription windowSubscription;
+  windowSubscription =
       dom.Subscription(dom.window, 'message', allowInterop((dom.Event event) {
     // A message on the Window can theoretically come from any website. It's
     // very unlikely that a malicious site would care about hacking someone's
     // unit tests, let alone be able to find the test server while it's
     // running, but it's good practice to check the origin anyway.
-    dom.MessageEvent message = event as dom.MessageEvent;
+    var message = event as dom.MessageEvent;
     if (message.origin != dom.window.location.origin) return;
-
-    // TODO(nweiz): Stop manually checking href here once issue 22554 is
-    // fixed.
-    if (message.data['href'] != iframe.src) return;
+    // Disambiguate between frames for different test suites.
+    // Depending on the source type, the `location.href` may be missing.
+    var location = js_util.getProperty(message.source, 'location') as Object?;
+    if (location == null) return;
+    if (js_util.getProperty(location, 'href') != iframe.src) return;
 
     message.stopPropagation();
+    windowSubscription.cancel();
 
-    if (message.data['ready'] == true) {
-      // This message indicates that the iframe is actively listening for
-      // events, so the message channel's second port can now be transferred.
-      channel.port2.start();
-      // TODO(#1758): This is a work around for a crash in package:build.
-      js_util.callMethod(
-          js_util.getProperty(iframe, 'contentWindow'), 'postMessage', [
-        'port',
-        dom.window.location.origin,
-        [channel.port2]
-      ]);
-      readyCompleter.complete();
-    } else if (message.data['exception'] == true) {
-      // This message from `dart.js` indicates that an exception occurred
-      // loading the test.
-      controller.local.sink.add(message.data['data']);
+    switch (message.data) {
+      case 'port':
+        // The frame is starting and sending a port to forward for the suite.
+        final port = message.ports.first;
+        _domSubscriptions[id] =
+            dom.Subscription(port, 'message', allowInterop((event) {
+          controller.local.sink.add((event as dom.MessageEvent).data);
+        }));
+        port.start();
+
+        _subscriptions[id] = controller.local.stream.listen(port.postMessage);
+      case {'ready': true}:
+        // This message indicates that the iframe is actively listening for
+        // events, so the message channel's second port can now be transferred.
+        var channel = dom.createMessageChannel();
+        assert(!_domSubscriptions.containsKey(id));
+        _domSubscriptions[id] = dom.Subscription(channel.port1, 'message',
+            allowInterop((dom.Event event) {
+          controller.local.sink.add((event as dom.MessageEvent).data['data']);
+        }));
+
+        assert(!_subscriptions.containsKey(id));
+        _subscriptions[id] =
+            controller.local.stream.listen(channel.port1.postMessage);
+        channel
+          ..port2.start()
+          ..port1.start();
+        // TODO(#1758): This is a work around for a crash in package:build.
+        js_util.callMethod(
+            js_util.getProperty(iframe, 'contentWindow'), 'postMessage', [
+          'port',
+          dom.window.location.origin,
+          [channel.port2]
+        ]);
+      case {'exception': true, 'data': final data}:
+        // This message from `dart.js` indicates that an exception occurred
+        // loading the test.
+        controller.local.sink.add(data);
     }
-  })));
-
-  channel.port1.start();
-  domSubscriptions.add(dom.Subscription(channel.port1, 'message',
-      allowInterop((dom.Event event) {
-    controller.local.sink.add((event as dom.MessageEvent).data['data']);
-  })));
-
-  subscriptions.add(controller.local.stream.listen((message) async {
-    await readyCompleter.future;
-
-    channel.port1.postMessage(message);
   }));
 
+  iframe.src = url;
+  dom.document.body!.appendChild(iframe);
+
   return controller.foreign;
 }
diff --git a/pkgs/test_api/CHANGELOG.md b/pkgs/test_api/CHANGELOG.md
index 1632870..22731cb 100644
--- a/pkgs/test_api/CHANGELOG.md
+++ b/pkgs/test_api/CHANGELOG.md
@@ -1,3 +1,48 @@
+## 0.6.1
+
+* Drop support for null unsafe Dart, bump SDK constraint to `3.0.0`.
+* Make some implementation classes `final`. These classes were never intended to
+  be extended or implemented. `Metadata`, `PlatformSelector`, `RemoteListener`,
+  `Runtime`, `StackTraceFormatter`, `SuitePlatform`, `RemoteException`,
+  `TestHandle`, `OutstandingWork`, `OutsideTestException`, `OnPlatform`,
+  `Retry`, `Skip`, `Tags`, `TestOn`, `Timeout`.
+* Mark an implementation class `interface`: `StackTraceMapper`.
+* Change the `Compiler` class into an `enum`.
+* Make `Fake` a `mixin class`.
+* Allow the latest analyzer (6.x.x).
+
+## 0.6.0
+
+* Remove the `package:test_api/expect.dart' library. `test` will export from
+  `package:matcher` directly.
+* Fix compatibility with wasm number semantics.
+
+## 0.5.2
+
+* Remove deprecation for the `scaffolding.dart` and `backend.dart` libraries.
+* Export `registerException` from the `scaffolding.dart` library.
+
+## 0.5.1
+
+* Handle a missing `'compiler'` value when running a test compiled against a
+  newer `test_api` than the runner back end is using. The expectation was that
+  the json protocol is only used across packages compatible with the same major
+  version of the `test_api` package, but `flutter test` does not check the
+  version of packages in the pub solve for user test code.
+
+## 0.5.0
+
+* Add `Compiler` class, exposed through `backend.dart`.
+* Support compiler identifiers in platform selectors.
+* Add `compiler` field to `SuitePlatform`. This will become required in the next
+  major release.
+* **BREAKING** Add required `defaultCompiler` and `supportedCompilers` fields
+  to `Runtime`.
+* Add `package:test_api/hooks_testing.dart` library for writing tests against
+  code that uses `package:test_api/hooks.dart`.
+* **BREAKING** Remove `ErrorFormatter`, `expectAsync`,  `throws`, and `Throws`
+  from `package:test_api/test_api.dart`.
+
 ## 0.4.18
 
 * Don't run `tearDown` until the test body and outstanding work is complete,
diff --git a/pkgs/test_api/README.md b/pkgs/test_api/README.md
index 27c759b..aa1af49 100644
--- a/pkgs/test_api/README.md
+++ b/pkgs/test_api/README.md
@@ -1,3 +1,6 @@
+[![pub package](https://img.shields.io/pub/v/test_api.svg)](https://pub.dev/packages/test_api)
+[![package publisher](https://img.shields.io/pub/publisher/test_api.svg)](https://pub.dev/packages/test_api/publisher)
+
 A minimal package for writing tests. At this time this package is not intended
 to be publicly used as the API will take time to stabilize.
 
diff --git a/pkgs/test_api/lib/backend.dart b/pkgs/test_api/lib/backend.dart
index bb80812..5da47b6 100644
--- a/pkgs/test_api/lib/backend.dart
+++ b/pkgs/test_api/lib/backend.dart
@@ -2,10 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-@Deprecated('package:test_api is not intended for general use. '
-    'Please use package:test.')
-library test_api.backend;
-
+export 'src/backend/compiler.dart' show Compiler;
 export 'src/backend/metadata.dart' show Metadata;
 export 'src/backend/platform_selector.dart' show PlatformSelector;
 export 'src/backend/remote_exception.dart' show RemoteException;
diff --git a/pkgs/test_api/lib/expect.dart b/pkgs/test_api/lib/expect.dart
deleted file mode 100644
index 30a8071..0000000
--- a/pkgs/test_api/lib/expect.dart
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-export 'package:matcher/matcher.dart';
-
-export 'src/expect/expect.dart' show expect, expectLater, fail;
-export 'src/expect/expect_async.dart'
-    show
-        Func0,
-        Func1,
-        Func2,
-        Func3,
-        Func4,
-        Func5,
-        Func6,
-        expectAsync0,
-        expectAsync1,
-        expectAsync2,
-        expectAsync3,
-        expectAsync4,
-        expectAsync5,
-        expectAsync6,
-        expectAsyncUntil0,
-        expectAsyncUntil1,
-        expectAsyncUntil2,
-        expectAsyncUntil3,
-        expectAsyncUntil4,
-        expectAsyncUntil5,
-        expectAsyncUntil6;
-export 'src/expect/future_matchers.dart'
-    show completes, completion, doesNotComplete;
-export 'src/expect/never_called.dart' show neverCalled;
-export 'src/expect/prints_matcher.dart' show prints;
-export 'src/expect/stream_matcher.dart' show StreamMatcher;
-export 'src/expect/stream_matchers.dart'
-    show
-        emitsDone,
-        emits,
-        emitsError,
-        mayEmit,
-        emitsAnyOf,
-        emitsInOrder,
-        emitsInAnyOrder,
-        emitsThrough,
-        mayEmitMultiple,
-        neverEmits;
-export 'src/expect/throws_matcher.dart' show throwsA;
-export 'src/expect/throws_matchers.dart'
-    show
-        throwsArgumentError,
-        throwsConcurrentModificationError,
-        throwsCyclicInitializationError,
-        throwsException,
-        throwsFormatException,
-        throwsNoSuchMethodError,
-        throwsNullThrownError,
-        throwsRangeError,
-        throwsStateError,
-        throwsUnimplementedError,
-        throwsUnsupportedError;
diff --git a/pkgs/test_api/lib/hooks.dart b/pkgs/test_api/lib/hooks.dart
index b7e1455..126d322 100644
--- a/pkgs/test_api/lib/hooks.dart
+++ b/pkgs/test_api/lib/hooks.dart
@@ -13,7 +13,7 @@
 export 'src/backend/test_failure.dart' show TestFailure;
 export 'src/scaffolding/utils.dart' show pumpEventQueue;
 
-class TestHandle {
+final class TestHandle {
   /// Returns handle for the currently running test.
   ///
   /// This must be called from within the zone that the test is running in. If
@@ -65,7 +65,7 @@
       _stackTraceFormatter.formatStackTrace(stackTrace);
 }
 
-class OutstandingWork {
+final class OutstandingWork {
   final Invoker _invoker;
   final Zone _zone;
   var _isComplete = false;
@@ -79,4 +79,4 @@
   }
 }
 
-class OutsideTestException implements Exception {}
+final class OutsideTestException implements Exception {}
diff --git a/pkgs/test_api/lib/hooks_testing.dart b/pkgs/test_api/lib/hooks_testing.dart
new file mode 100644
index 0000000..b0a6154
--- /dev/null
+++ b/pkgs/test_api/lib/hooks_testing.dart
@@ -0,0 +1,157 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'src/backend/group.dart';
+import 'src/backend/invoker.dart';
+import 'src/backend/live_test.dart';
+import 'src/backend/metadata.dart';
+import 'src/backend/runtime.dart';
+import 'src/backend/state.dart';
+import 'src/backend/suite.dart';
+import 'src/backend/suite_platform.dart';
+
+@Deprecated('These classes are unused for monitoring tests. Use `State`.')
+export 'src/backend/state.dart' show Result, Status;
+export 'src/backend/test_failure.dart' show TestFailure;
+
+/// A monitor for the behavior of a callback when it is run as the body of a
+/// test case.
+///
+/// Allows running a callback as the body of a local test case and querying for
+/// the current [state], and [errors], and subscribing to future errors.
+///
+/// Use [run] to run a test body and query for the success or failure.
+///
+/// Use [start] to start a test and query for whether it has finished running.
+final class TestCaseMonitor {
+  final LiveTest _liveTest;
+  final _done = Completer<void>();
+  TestCaseMonitor._(FutureOr<void> Function() body)
+      : _liveTest = _createTest(body);
+
+  /// Run [body] as a test case and return a [TestCaseMonitor] with the result.
+  ///
+  /// The [state] will either [State.passed], [State.skipped], or
+  /// [State.failed], the test will no longer be running.
+  ///
+  /// {@template result-late-fail}
+  /// Note that a test can change state from [State.passed] to [State.failed]
+  /// if the test surfaces an unawaited asynchronous error.
+  /// {@endtemplate}
+  ///
+  /// ```dart
+  /// final monitor = await TestCaseMonitor.run(() {
+  ///   fail('oh no!');
+  /// });
+  /// assert(monitor.state == State.failed);
+  /// assert((monitor.errors.single.error as TestFailure).message == 'oh no!');
+  /// ```
+  static Future<TestCaseMonitor> run(FutureOr<void> Function() body) async {
+    final monitor = TestCaseMonitor.start(body);
+    await monitor.onDone;
+    return monitor;
+  }
+
+  /// Start [body] as a test case and return a [TestCaseMonitor] with the status
+  /// and result.
+  ///
+  /// The [state] will start as [State.pending] if queried synchronously, but it
+  /// will switch to [State.running]. After `onDone` completes the state will be
+  /// one of [State.passed], [State.skipped], or [State.failed].
+  ///
+  /// {@macro result-late-fail}
+  ///
+  /// ```dart
+  /// late void Function() completeWork;
+  /// final monitor = TestCaseMonitor.start(() {
+  ///   final outstandingWork = TestHandle.current.markPending();
+  ///   completeWork = outstandingWork.complete;
+  /// });
+  /// await pumpEventQueue();
+  /// assert(monitor.state == State.running);
+  /// completeWork();
+  /// await monitor.onDone;
+  /// assert(monitor.state == State.passed);
+  /// ```
+  static TestCaseMonitor start(FutureOr<void> Function() body) =>
+      TestCaseMonitor._(body).._start();
+
+  void _start() {
+    _liveTest.run().whenComplete(_done.complete);
+  }
+
+  /// A future that completes after this test has finished running, or has
+  /// surfaced an error.
+  Future<void> get onDone => _done.future;
+
+  /// The running and success or failure status for the test case.
+  State get state {
+    final status = _liveTest.state.status;
+    if (status == Status.pending) return State.pending;
+    if (status == Status.running) return State.running;
+    final result = _liveTest.state.result;
+    if (result == Result.skipped) return State.skipped;
+    if (result == Result.success) return State.passed;
+    // result == Result.failure || result == Result.error
+    return State.failed;
+  }
+
+  /// The errors surfaced by the test.
+  ///
+  /// A test with any errors will have a [state] of [State.failed].
+  ///
+  /// {@macro result-late-fail}
+  ///
+  /// A test may have more than one error if there were unhandled asynchronous
+  /// errors surfaced after the test is done.
+  Iterable<AsyncError> get errors => _liveTest.errors;
+
+  /// A stream of errors surfaced by the test.
+  ///
+  /// This stream will not close, asynchronous errors may be surfaced within the
+  /// test's error zone at any point.
+  Stream<AsyncError> get onError => _liveTest.onError;
+}
+
+/// Returns a local [LiveTest] that runs [body].
+LiveTest _createTest(FutureOr<void> Function() body) {
+  var test = LocalTest('test', Metadata(chainStackTraces: true), body);
+  var suite = Suite(Group.root([test]), _suitePlatform, ignoreTimeouts: false);
+  return test.load(suite);
+}
+
+/// A dummy suite platform to use for testing suites.
+final _suitePlatform =
+    SuitePlatform(Runtime.vm, compiler: Runtime.vm.defaultCompiler);
+
+/// The running and success state of a test monitored by a [TestCaseMonitor].
+enum State {
+  /// The test is has not yet started.
+  pending,
+
+  /// The test is running and has not yet failed.
+  running,
+
+  /// The test has completed without any error.
+  ///
+  /// This implies that the test body has completed, and no error has surfaced
+  /// *yet*. However, it this doesn't mean that the test won't fail in the
+  /// future.
+  passed,
+
+  /// The test, or some part of it, has been skipped.
+  ///
+  /// This does not imply that the test has not had an error, but if there are
+  /// errors they are ignored.
+  skipped,
+
+  /// The test has failed.
+  ///
+  /// An test fails when any exception, typically a [TestFailure], is thrown in
+  /// the test's zone. A test that has failed may still have additional errors
+  /// that surface as unhandled asynchronous errors.
+  failed,
+}
diff --git a/pkgs/test_api/lib/scaffolding.dart b/pkgs/test_api/lib/scaffolding.dart
index 57f9e9a..84185b8 100644
--- a/pkgs/test_api/lib/scaffolding.dart
+++ b/pkgs/test_api/lib/scaffolding.dart
@@ -8,8 +8,6 @@
 /// {@canonicalFor tags.Tags}
 /// {@canonicalFor test_on.TestOn}
 /// {@canonicalFor timeout.Timeout}
-@Deprecated('package:test_api is not intended for general use. '
-    'Please use package:test.')
 library test_api.scaffolding;
 
 export 'src/backend/configuration/on_platform.dart' show OnPlatform;
@@ -18,8 +16,8 @@
 export 'src/backend/configuration/tags.dart' show Tags;
 export 'src/backend/configuration/test_on.dart' show TestOn;
 export 'src/backend/configuration/timeout.dart' show Timeout;
-export 'src/scaffolding/spawn_hybrid.dart' show spawnHybridUri, spawnHybridCode;
+export 'src/scaffolding/spawn_hybrid.dart' show spawnHybridCode, spawnHybridUri;
 export 'src/scaffolding/test_structure.dart'
-    show group, test, setUp, setUpAll, tearDown, tearDownAll, addTearDown;
+    show addTearDown, group, setUp, setUpAll, tearDown, tearDownAll, test;
 export 'src/scaffolding/utils.dart'
-    show pumpEventQueue, printOnFailure, markTestSkipped;
+    show markTestSkipped, printOnFailure, pumpEventQueue, registerException;
diff --git a/pkgs/test_api/lib/src/backend/compiler.dart b/pkgs/test_api/lib/src/backend/compiler.dart
new file mode 100644
index 0000000..9d8c3f9
--- /dev/null
+++ b/pkgs/test_api/lib/src/backend/compiler.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// All the Dart compilers supported by the test runner.
+enum Compiler {
+  /// The production Dart to Javascript compiler (whole world, optimizing).
+  dart2js('Dart2Js', 'dart2js'),
+
+  /// Experimental Dart to Wasm compiler.
+  dart2wasm('Dart2WASM', 'dart2wasm'),
+
+  /// Compiles dart code to a native executable.
+  exe('Exe', 'exe'),
+
+  /// The standard compiler for vm tests, compiles tests to kernel before
+  /// running them on the VM.
+  kernel('Kernel', 'kernel'),
+
+  /// Runs tests directly from source, with no precompilation.
+  source('Source', 'source');
+
+  /// The compilers that are supported by the test runner by default.
+  static const List<Compiler> builtIn = [
+    Compiler.dart2js,
+    Compiler.dart2wasm,
+    Compiler.exe,
+    Compiler.kernel,
+    Compiler.source,
+  ];
+
+  /// The human-friendly name of the compiler.
+  final String name;
+
+  /// The identifier used to look up the compiler.
+  final String identifier;
+
+  const Compiler(this.name, this.identifier);
+
+  /// Converts a JSON-safe representation generated by [serialize] back into a
+  /// [Compiler].
+  ///
+  /// Note that custom [Compiler] implementations are not supported.
+  factory Compiler.deserialize(Object serialized) => builtIn
+      .firstWhere((compiler) => compiler.identifier == serialized as String);
+
+  /// Converts [this] into a JSON-safe object that can be converted back to a
+  /// [Compiler] using [Compiler.deserialize].
+  Object serialize() => identifier;
+
+  @override
+  String toString() => name;
+}
diff --git a/pkgs/test_api/lib/src/backend/configuration/on_platform.dart b/pkgs/test_api/lib/src/backend/configuration/on_platform.dart
index d88848d..02a5254 100644
--- a/pkgs/test_api/lib/src/backend/configuration/on_platform.dart
+++ b/pkgs/test_api/lib/src/backend/configuration/on_platform.dart
@@ -10,7 +10,7 @@
 ///
 /// [onPlatform]: https://github.com/dart-lang/test/tree/master/pkgs/test#platform-specific-configuration
 @Target({TargetKind.library})
-class OnPlatform {
+final class OnPlatform {
   final Map<String, dynamic> annotationsByPlatform;
 
   const OnPlatform(this.annotationsByPlatform);
diff --git a/pkgs/test_api/lib/src/backend/configuration/retry.dart b/pkgs/test_api/lib/src/backend/configuration/retry.dart
index b813526..1811814 100644
--- a/pkgs/test_api/lib/src/backend/configuration/retry.dart
+++ b/pkgs/test_api/lib/src/backend/configuration/retry.dart
@@ -9,7 +9,7 @@
 /// A suite-level retry configuration will enable retries for every test in the
 /// suite, unless the group or test is configured with a more specific retry.
 @Target({TargetKind.library})
-class Retry {
+final class Retry {
   /// The number of times the tests in the suite will be retried.
   final int count;
 
diff --git a/pkgs/test_api/lib/src/backend/configuration/skip.dart b/pkgs/test_api/lib/src/backend/configuration/skip.dart
index 8be4b73..3927994 100644
--- a/pkgs/test_api/lib/src/backend/configuration/skip.dart
+++ b/pkgs/test_api/lib/src/backend/configuration/skip.dart
@@ -6,7 +6,7 @@
 
 /// An annotation for marking a test suite as skipped.
 @Target({TargetKind.library})
-class Skip {
+final class Skip {
   /// The reason the test suite is skipped, or `null` if no reason is given.
   final String? reason;
 
diff --git a/pkgs/test_api/lib/src/backend/configuration/tags.dart b/pkgs/test_api/lib/src/backend/configuration/tags.dart
index cb1ea2b..dbd03f3 100644
--- a/pkgs/test_api/lib/src/backend/configuration/tags.dart
+++ b/pkgs/test_api/lib/src/backend/configuration/tags.dart
@@ -10,7 +10,7 @@
 ///
 /// [tagging tests]: https://github.com/dart-lang/test/blob/master/pkgs/test/README.md#tagging-tests
 @Target({TargetKind.library})
-class Tags {
+final class Tags {
   /// The tags for the test suite.
   Set<String> get tags => _tags.toSet();
 
diff --git a/pkgs/test_api/lib/src/backend/configuration/test_on.dart b/pkgs/test_api/lib/src/backend/configuration/test_on.dart
index 4ffb016..dee7f40 100644
--- a/pkgs/test_api/lib/src/backend/configuration/test_on.dart
+++ b/pkgs/test_api/lib/src/backend/configuration/test_on.dart
@@ -10,7 +10,7 @@
 ///
 /// [the README]: https://github.com/dart-lang/test/tree/master/pkgs/test#platform-selectors
 @Target({TargetKind.library})
-class TestOn {
+final class TestOn {
   /// The expression specifying the platform.
   final String expression;
 
diff --git a/pkgs/test_api/lib/src/backend/configuration/timeout.dart b/pkgs/test_api/lib/src/backend/configuration/timeout.dart
index 5532318..e51d520 100644
--- a/pkgs/test_api/lib/src/backend/configuration/timeout.dart
+++ b/pkgs/test_api/lib/src/backend/configuration/timeout.dart
@@ -24,7 +24,7 @@
 /// can be overridden entirely; with [Timeout.factor], it can be scaled
 /// relative to the default.
 @Target({TargetKind.library})
-class Timeout {
+final class Timeout {
   /// A constant indicating that a test should never time out.
   static const none = Timeout._none();
 
@@ -79,7 +79,7 @@
 
     // Scan a number. This will be either a time unit or a scale factor.
     scanner.expect(_untilUnit, name: 'number');
-    var number = double.parse((scanner.lastMatch![0])!);
+    var number = double.parse(scanner.lastMatch![0]!);
 
     // A number followed by "x" is a scale factor.
     if (scanner.scan('x') || scanner.scan('X')) {
@@ -92,13 +92,13 @@
     var microseconds = 0.0;
     while (true) {
       scanner.expect(_unit, name: 'unit');
-      microseconds += _microsecondsFor(number, (scanner.lastMatch![0])!);
+      microseconds += _microsecondsFor(number, scanner.lastMatch![0]!);
 
       scanner.scan(_whitespace);
 
       // Scan the next number, if it's available.
       if (!scanner.scan(_untilUnit)) break;
-      number = double.parse((scanner.lastMatch![0])!);
+      number = double.parse(scanner.lastMatch![0]!);
     }
 
     scanner.expectDone();
@@ -106,24 +106,15 @@
   }
 
   /// Returns the number of microseconds in [number] [unit]s.
-  static double _microsecondsFor(double number, String unit) {
-    switch (unit) {
-      case 'd':
-        return number * 24 * 60 * 60 * 1000000;
-      case 'h':
-        return number * 60 * 60 * 1000000;
-      case 'm':
-        return number * 60 * 1000000;
-      case 's':
-        return number * 1000000;
-      case 'ms':
-        return number * 1000;
-      case 'us':
-        return number;
-      default:
-        throw ArgumentError('Unknown unit $unit.');
-    }
-  }
+  static double _microsecondsFor(double number, String unit) => switch (unit) {
+        'd' => number * 24 * 60 * 60 * 1000000,
+        'h' => number * 60 * 60 * 1000000,
+        'm' => number * 60 * 1000000,
+        's' => number * 1000000,
+        'ms' => number * 1000,
+        'us' => number,
+        _ => throw ArgumentError('Unknown unit $unit.'),
+      };
 
   /// Returns a new [Timeout] that merges [this] with [other].
   ///
@@ -150,7 +141,7 @@
   int get hashCode => duration.hashCode ^ 5 * scaleFactor.hashCode;
 
   @override
-  bool operator ==(other) =>
+  bool operator ==(Object other) =>
       other is Timeout &&
       other.duration == duration &&
       other.scaleFactor == scaleFactor;
diff --git a/pkgs/test_api/lib/src/backend/declarer.dart b/pkgs/test_api/lib/src/backend/declarer.dart
index 7a37552..c3686dd 100644
--- a/pkgs/test_api/lib/src/backend/declarer.dart
+++ b/pkgs/test_api/lib/src/backend/declarer.dart
@@ -172,9 +172,9 @@
   void test(String name, dynamic Function() body,
       {String? testOn,
       Timeout? timeout,
-      skip,
+      Object? skip,
       Map<String, dynamic>? onPlatform,
-      tags,
+      Object? tags,
       int? retry,
       bool solo = false}) {
     _checkNotBuilt('test');
@@ -228,9 +228,9 @@
   void group(String name, void Function() body,
       {String? testOn,
       Timeout? timeout,
-      skip,
+      Object? skip,
       Map<String, dynamic>? onPlatform,
-      tags,
+      Object? tags,
       int? retry,
       bool solo = false}) {
     _checkNotBuilt('group');
diff --git a/pkgs/test_api/lib/src/backend/invoker.dart b/pkgs/test_api/lib/src/backend/invoker.dart
index 582d9f9..0274f90 100644
--- a/pkgs/test_api/lib/src/backend/invoker.dart
+++ b/pkgs/test_api/lib/src/backend/invoker.dart
@@ -305,9 +305,9 @@
       // Set the state explicitly so we don't get an extra error about the test
       // failing after being complete.
       _controller.setState(const State(Status.complete, Result.error));
-      throw 'This test was marked as skipped after it had already completed. '
-          'Make sure to use\n'
-          '[expectAsync] or the [completes] matcher when testing async code.';
+      throw 'This test was marked as skipped after it had already completed.\n'
+          'Make sure to use a matching library which informs the test runner\n'
+          'of pending async work.';
     }
 
     if (message != null) _controller.message(Message.skip(message));
@@ -367,9 +367,9 @@
 
     _handleError(
         zone,
-        'This test failed after it had already completed. Make sure to use '
-        '[expectAsync]\n'
-        'or the [completes] matcher when testing async code.',
+        'This test failed after it had already completed.\n'
+        'Make sure to use a matching library which informs the test runner\n'
+        'of pending async work.',
         stackTrace);
   }
 
diff --git a/pkgs/test_api/lib/src/backend/live_test_controller.dart b/pkgs/test_api/lib/src/backend/live_test_controller.dart
index 94994c1..956c293 100644
--- a/pkgs/test_api/lib/src/backend/live_test_controller.dart
+++ b/pkgs/test_api/lib/src/backend/live_test_controller.dart
@@ -48,7 +48,7 @@
 
   /// The current state of the test.
   @override
-  var state = const State(Status.pending, Result.success);
+  State state = const State(Status.pending, Result.success);
 
   /// The controller for [onStateChange].
   ///
diff --git a/pkgs/test_api/lib/src/backend/message.dart b/pkgs/test_api/lib/src/backend/message.dart
index efe152f..a027460 100644
--- a/pkgs/test_api/lib/src/backend/message.dart
+++ b/pkgs/test_api/lib/src/backend/message.dart
@@ -28,16 +28,11 @@
   /// The name of the message type.
   final String name;
 
-  factory MessageType.parse(String name) {
-    switch (name) {
-      case 'print':
-        return MessageType.print;
-      case 'skip':
-        return MessageType.skip;
-      default:
-        throw ArgumentError('Invalid message type "$name".');
-    }
-  }
+  factory MessageType.parse(String name) => switch (name) {
+        'print' => MessageType.print,
+        'skip' => MessageType.skip,
+        _ => throw ArgumentError('Invalid message type "$name".'),
+      };
 
   const MessageType._(this.name);
 
diff --git a/pkgs/test_api/lib/src/backend/metadata.dart b/pkgs/test_api/lib/src/backend/metadata.dart
index 0404dbf..3455a04 100644
--- a/pkgs/test_api/lib/src/backend/metadata.dart
+++ b/pkgs/test_api/lib/src/backend/metadata.dart
@@ -16,7 +16,7 @@
 ///
 /// This metadata comes from declarations on the test itself; it doesn't include
 /// configuration from the user.
-class Metadata {
+final class Metadata {
   /// Empty metadata with only default values.
   ///
   /// Using this is slightly more efficient than manually constructing a new
@@ -264,7 +264,7 @@
         skipReason = serialized['skipReason'] as String?,
         _verboseTrace = serialized['verboseTrace'] as bool?,
         _chainStackTraces = serialized['chainStackTraces'] as bool?,
-        _retry = serialized['retry'] as int?,
+        _retry = (serialized['retry'] as num?)?.toInt(),
         tags = Set.from(serialized['tags'] as Iterable),
         onPlatform = {
           for (var pair in serialized['onPlatform'] as List)
@@ -282,7 +282,8 @@
     if (serialized == 'none') return Timeout.none;
     var scaleFactor = serialized['scaleFactor'];
     if (scaleFactor != null) return Timeout.factor(scaleFactor as num);
-    return Timeout(Duration(microseconds: serialized['duration'] as int));
+    return Timeout(
+        Duration(microseconds: (serialized['duration'] as num).toInt()));
   }
 
   /// Throws an [ArgumentError] if any tags in [tags] aren't hyphenated
diff --git a/pkgs/test_api/lib/src/backend/operating_system.dart b/pkgs/test_api/lib/src/backend/operating_system.dart
index f33e739..a86c1e7 100644
--- a/pkgs/test_api/lib/src/backend/operating_system.dart
+++ b/pkgs/test_api/lib/src/backend/operating_system.dart
@@ -49,22 +49,14 @@
   /// `Platform.operatingSystem`.
   ///
   /// If no operating system is found, returns [none].
-  static OperatingSystem findByIoName(String name) {
-    switch (name) {
-      case 'windows':
-        return windows;
-      case 'macos':
-        return macOS;
-      case 'linux':
-        return linux;
-      case 'android':
-        return android;
-      case 'ios':
-        return iOS;
-      default:
-        return none;
-    }
-  }
+  static OperatingSystem findByIoName(String name) => switch (name) {
+        'windows' => windows,
+        'macos' => macOS,
+        'linux' => linux,
+        'android' => android,
+        'ios' => iOS,
+        _ => none,
+      };
 
   /// The human-friendly of the operating system.
   final String name;
diff --git a/pkgs/test_api/lib/src/backend/platform_selector.dart b/pkgs/test_api/lib/src/backend/platform_selector.dart
index 8d6d60c..2ad59b2 100644
--- a/pkgs/test_api/lib/src/backend/platform_selector.dart
+++ b/pkgs/test_api/lib/src/backend/platform_selector.dart
@@ -5,6 +5,7 @@
 import 'package:boolean_selector/boolean_selector.dart';
 import 'package:source_span/source_span.dart';
 
+import 'compiler.dart';
 import 'operating_system.dart';
 import 'runtime.dart';
 import 'suite_platform.dart';
@@ -19,6 +20,7 @@
   'google',
   'wasm',
   for (var runtime in Runtime.builtIn) runtime.identifier,
+  for (var compiler in Compiler.builtIn) compiler.identifier,
   for (var os in OperatingSystem.all) os.identifier,
 };
 
@@ -28,7 +30,7 @@
 /// This uses the [boolean selector][] syntax.
 ///
 /// [boolean selector]: https://pub.dev/packages/boolean_selector
-class PlatformSelector {
+final class PlatformSelector {
   /// A selector that declares that a test can be run on all platforms.
   static const all = PlatformSelector._(BooleanSelector.all);
 
@@ -77,31 +79,23 @@
   }
 
   /// Returns whether the selector matches the given [platform].
-  bool evaluate(SuitePlatform platform) {
-    return _inner.evaluate((String variable) {
-      if (variable == platform.runtime.identifier) return true;
-      if (variable == platform.runtime.parent?.identifier) return true;
-      if (variable == platform.os.identifier) return true;
-      switch (variable) {
-        case 'dart-vm':
-          return platform.runtime.isDartVM;
-        case 'browser':
-          return platform.runtime.isBrowser;
-        case 'js':
-          return platform.runtime.isJS;
-        case 'blink':
-          return platform.runtime.isBlink;
-        case 'posix':
-          return platform.os.isPosix;
-        case 'google':
-          return platform.inGoogle;
-        case 'wasm':
-          return platform.runtime.isWasm;
-        default:
-          return false;
-      }
-    });
-  }
+  bool evaluate(SuitePlatform platform) =>
+      _inner.evaluate((String variable) => switch (variable) {
+            _
+                when variable == platform.runtime.identifier ||
+                    variable == platform.runtime.parent?.identifier ||
+                    variable == platform.os.identifier ||
+                    variable == platform.compiler.identifier =>
+              true,
+            'dart-vm' => platform.runtime.isDartVM,
+            'browser' => platform.runtime.isBrowser,
+            'js' => platform.runtime.isJS,
+            'blink' => platform.runtime.isBlink,
+            'posix' => platform.os.isPosix,
+            'google' => platform.inGoogle,
+            'wasm' => platform.runtime.isWasm,
+            _ => false,
+          });
 
   /// Returns a new [PlatformSelector] that matches only platforms matched by
   /// both [this] and [other].
@@ -114,7 +108,7 @@
   String toString() => _inner.toString();
 
   @override
-  bool operator ==(other) =>
+  bool operator ==(Object other) =>
       other is PlatformSelector && _inner == other._inner;
 
   @override
diff --git a/pkgs/test_api/lib/src/backend/remote_exception.dart b/pkgs/test_api/lib/src/backend/remote_exception.dart
index ef47ea1..560f70e 100644
--- a/pkgs/test_api/lib/src/backend/remote_exception.dart
+++ b/pkgs/test_api/lib/src/backend/remote_exception.dart
@@ -12,7 +12,7 @@
 ///
 /// This could be an exception thrown in a different isolate, a different
 /// process, or on an entirely different computer.
-class RemoteException implements Exception {
+final class RemoteException implements Exception {
   /// The original exception's message, if it had one.
   ///
   /// If the original exception was a plain string, this will contain that
@@ -29,7 +29,7 @@
   ///
   /// Other than JSON- and isolate-safety, no guarantees are made about the
   /// serialized format.
-  static Map<String, dynamic> serialize(error, StackTrace stackTrace) {
+  static Map<String, dynamic> serialize(dynamic error, StackTrace stackTrace) {
     String? message;
     if (error is String) {
       message = error;
@@ -56,23 +56,21 @@
   ///
   /// The returned [AsyncError] is guaranteed to have a [RemoteException] as its
   /// error and a [Chain] as its stack trace.
-  static AsyncError deserialize(serialized) {
+  static AsyncError deserialize(Map serialized) {
     return AsyncError(_deserializeException(serialized),
         Chain.parse(serialized['stackChain'] as String));
   }
 
   /// Deserializes the exception portion of [serialized].
-  static RemoteException _deserializeException(serialized) {
+  static RemoteException _deserializeException(Map serialized) {
     final message = serialized['message'] as String?;
     final type = serialized['type'] as String;
     final toString = serialized['toString'] as String;
 
-    switch (serialized['supertype'] as String?) {
-      case 'TestFailure':
-        return _RemoteTestFailure(message, type, toString);
-      default:
-        return RemoteException._(message, type, toString);
-    }
+    return switch (serialized['supertype'] as String?) {
+      'TestFailure' => _RemoteTestFailure(message, type, toString),
+      _ => RemoteException._(message, type, toString),
+    };
   }
 
   RemoteException._(this.message, this.type, this._toString);
@@ -85,7 +83,7 @@
 ///
 /// It's important to preserve [TestFailure]-ness, because tests have different
 /// results depending on whether an exception was a failure or an error.
-class _RemoteTestFailure extends RemoteException implements TestFailure {
+final class _RemoteTestFailure extends RemoteException implements TestFailure {
   _RemoteTestFailure(String? message, String type, String toString)
       : super._(message, type, toString);
 }
diff --git a/pkgs/test_api/lib/src/backend/remote_listener.dart b/pkgs/test_api/lib/src/backend/remote_listener.dart
index 5aa0638..f47c4ea 100644
--- a/pkgs/test_api/lib/src/backend/remote_listener.dart
+++ b/pkgs/test_api/lib/src/backend/remote_listener.dart
@@ -20,7 +20,7 @@
 import 'suite_platform.dart';
 import 'test.dart';
 
-class RemoteListener {
+final class RemoteListener {
   /// The test suite to run.
   final Suite _suite;
 
diff --git a/pkgs/test_api/lib/src/backend/runtime.dart b/pkgs/test_api/lib/src/backend/runtime.dart
index 6b189c6..c70eb99 100644
--- a/pkgs/test_api/lib/src/backend/runtime.dart
+++ b/pkgs/test_api/lib/src/backend/runtime.dart
@@ -2,37 +2,57 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'compiler.dart';
+
 /// An enum of all Dart runtimes supported by the test runner.
-class Runtime {
+final class Runtime {
   // When adding new runtimes, be sure to update the baseline and derived
   // variable tests in test/backend/platform_selector/evaluate_test.
 
   /// The command-line Dart VM.
-  static const Runtime vm = Runtime('VM', 'vm', isDartVM: true);
+  static const Runtime vm = Runtime('VM', 'vm', Compiler.kernel,
+      [Compiler.kernel, Compiler.source, Compiler.exe],
+      isDartVM: true);
 
   /// Google Chrome.
-  static const Runtime chrome =
-      Runtime('Chrome', 'chrome', isBrowser: true, isJS: true, isBlink: true);
+  static const Runtime chrome = Runtime(
+      'Chrome', 'chrome', Compiler.dart2js, [Compiler.dart2js],
+      isBrowser: true, isJS: true, isBlink: true);
 
   /// Mozilla Firefox.
-  static const Runtime firefox =
-      Runtime('Firefox', 'firefox', isBrowser: true, isJS: true);
+  static const Runtime firefox = Runtime(
+      'Firefox', 'firefox', Compiler.dart2js, [Compiler.dart2js],
+      isBrowser: true, isJS: true);
 
   /// Apple Safari.
-  static const Runtime safari =
-      Runtime('Safari', 'safari', isBrowser: true, isJS: true);
+  static const Runtime safari = Runtime(
+      'Safari', 'safari', Compiler.dart2js, [Compiler.dart2js],
+      isBrowser: true, isJS: true);
 
   /// Microsoft Internet Explorer.
-  static const Runtime internetExplorer =
-      Runtime('Internet Explorer', 'ie', isBrowser: true, isJS: true);
+  static const Runtime internetExplorer = Runtime(
+      'Internet Explorer', 'ie', Compiler.dart2js, [Compiler.dart2js],
+      isBrowser: true, isJS: true);
+
+  /// Microsoft Edge (based on Chromium).
+  static const Runtime edge = Runtime(
+      'Microsoft Edge', 'edge', Compiler.dart2js, [Compiler.dart2js],
+      isBrowser: true, isJS: true, isBlink: true);
 
   /// The command-line Node.js VM.
-  static const Runtime nodeJS = Runtime('Node.js', 'node', isJS: true);
+  static const Runtime nodeJS = Runtime(
+      'Node.js', 'node', Compiler.dart2js, [Compiler.dart2js],
+      isJS: true);
 
   /// Google Chrome.
   static const Runtime experimentalChromeWasm = Runtime(
-      'ExperimentalChromeWasm', 'experimental-chrome-wasm',
-      isBrowser: true, isBlink: true, isWasm: true);
+      'ExperimentalChromeWasm',
+      'experimental-chrome-wasm',
+      Compiler.dart2wasm,
+      [Compiler.dart2wasm],
+      isBrowser: true,
+      isBlink: true,
+      isWasm: true);
 
   /// The platforms that are supported by the test runner by default.
   static const List<Runtime> builtIn = [
@@ -41,6 +61,7 @@
     Runtime.firefox,
     Runtime.safari,
     Runtime.internetExplorer,
+    Runtime.edge,
     Runtime.nodeJS,
     Runtime.experimentalChromeWasm,
   ];
@@ -82,7 +103,14 @@
   /// That is, returns [parent] if it's non-`null` or [this] if it's `null`.
   Runtime get root => parent ?? this;
 
-  const Runtime(this.name, this.identifier,
+  /// The default compiler to use with this runtime.
+  final Compiler defaultCompiler;
+
+  /// All the supported compilers for this runtime.
+  final List<Compiler> supportedCompilers;
+
+  const Runtime(
+      this.name, this.identifier, this.defaultCompiler, this.supportedCompilers,
       {this.isDartVM = false,
       this.isBrowser = false,
       this.isJS = false,
@@ -91,7 +119,8 @@
       this.isWasm = false})
       : parent = null;
 
-  Runtime._child(this.name, this.identifier, Runtime this.parent)
+  Runtime._child(this.name, this.identifier, this.defaultCompiler,
+      this.supportedCompilers, Runtime this.parent)
       : isDartVM = parent.isDartVM,
         isBrowser = parent.isBrowser,
         isJS = parent.isJS,
@@ -108,17 +137,26 @@
     }
 
     var map = serialized as Map;
+    var name = map['name'] as String;
+    var identifier = map['identifier'] as String;
+    var defaultCompiler =
+        Compiler.deserialize(map['defaultCompiler'] as Object);
+    var supportedCompilers = [
+      for (var compiler in map['supportedCompilers'] as List)
+        Compiler.deserialize(compiler as Object),
+    ];
+
     var parent = map['parent'];
     if (parent != null) {
       // Note that the returned platform's [parent] won't necessarily be `==` to
       // a separately-deserialized parent platform. This should be fine, though,
       // since we only deserialize platforms in the remote execution context
       // where they're only used to evaluate platform selectors.
-      return Runtime._child(map['name'] as String, map['identifier'] as String,
-          Runtime.deserialize(parent as Object));
+      return Runtime._child(name, identifier, defaultCompiler,
+          supportedCompilers, Runtime.deserialize(parent as Object));
     }
 
-    return Runtime(map['name'] as String, map['identifier'] as String,
+    return Runtime(name, identifier, defaultCompiler, supportedCompilers,
         isDartVM: map['isDartVM'] as bool,
         isBrowser: map['isBrowser'] as bool,
         isJS: map['isJS'] as bool,
@@ -135,6 +173,10 @@
     if (parent != null) {
       return {
         'name': name,
+        'defaultCompiler': defaultCompiler.serialize(),
+        'supportedCompilers': [
+          for (var compiler in supportedCompilers) compiler.serialize(),
+        ],
         'identifier': identifier,
         'parent': parent!.serialize()
       };
@@ -142,6 +184,10 @@
 
     return {
       'name': name,
+      'defaultCompiler': defaultCompiler.serialize(),
+      'supportedCompilers': [
+        for (var compiler in supportedCompilers) compiler.serialize(),
+      ],
       'identifier': identifier,
       'isDartVM': isDartVM,
       'isBrowser': isBrowser,
@@ -157,7 +203,10 @@
   ///
   /// This may not be called on a platform that's already a child.
   Runtime extend(String name, String identifier) {
-    if (parent == null) return Runtime._child(name, identifier, this);
+    if (parent == null) {
+      return Runtime._child(
+          name, identifier, defaultCompiler, supportedCompilers, this);
+    }
     throw StateError('A child platform may not be extended.');
   }
 
diff --git a/pkgs/test_api/lib/src/backend/stack_trace_formatter.dart b/pkgs/test_api/lib/src/backend/stack_trace_formatter.dart
index d200143..a495e89 100644
--- a/pkgs/test_api/lib/src/backend/stack_trace_formatter.dart
+++ b/pkgs/test_api/lib/src/backend/stack_trace_formatter.dart
@@ -17,13 +17,13 @@
 ///
 /// This can convert JavaScript stack traces to Dart using source maps, and fold
 /// irrelevant frames out of the stack trace.
-class StackTraceFormatter {
+final class StackTraceFormatter {
   /// A class that converts [trace] into a Dart stack trace, or `null` to use it
   /// as-is.
   StackTraceMapper? _mapper;
 
   /// The set of packages to fold when producing terse [Chain]s.
-  var _except = {'test', 'stream_channel', 'test_api'};
+  var _except = {'matcher', 'stream_channel', 'test', 'test_api'};
 
   /// If non-empty, all packages not in this list will be folded when producing
   /// terse [Chain]s.
diff --git a/pkgs/test_api/lib/src/backend/stack_trace_mapper.dart b/pkgs/test_api/lib/src/backend/stack_trace_mapper.dart
index fd7298b..b091bbe 100644
--- a/pkgs/test_api/lib/src/backend/stack_trace_mapper.dart
+++ b/pkgs/test_api/lib/src/backend/stack_trace_mapper.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// A class for mapping JS stack traces to Dart stack traces using source maps.
-abstract class StackTraceMapper {
+abstract interface class StackTraceMapper {
   /// Converts [trace] into a Dart stack trace.
   StackTrace mapStackTrace(StackTrace trace);
 
diff --git a/pkgs/test_api/lib/src/backend/state.dart b/pkgs/test_api/lib/src/backend/state.dart
index ba82cd0..5a37654 100644
--- a/pkgs/test_api/lib/src/backend/state.dart
+++ b/pkgs/test_api/lib/src/backend/state.dart
@@ -28,7 +28,7 @@
   const State(this.status, this.result);
 
   @override
-  bool operator ==(other) =>
+  bool operator ==(Object other) =>
       other is State && status == other.status && result == other.result;
 
   @override
@@ -44,12 +44,12 @@
 }
 
 /// Where the test is in its process of running.
-class Status {
+enum Status {
   /// The test has not yet begun running.
-  static const pending = Status._('pending');
+  pending,
 
   /// The test is currently running.
-  static const running = Status._('running');
+  running,
 
   /// The test has finished running.
   ///
@@ -58,56 +58,37 @@
   /// first error or when all [expectAsync] callbacks have been called and any
   /// returned [Future] has completed, but it's possible for further processing
   /// to happen, which may cause further errors.
-  static const complete = Status._('complete');
+  complete;
 
-  /// The name of the status.
-  final String name;
-
-  factory Status.parse(String name) {
-    switch (name) {
-      case 'pending':
-        return Status.pending;
-      case 'running':
-        return Status.running;
-      case 'complete':
-        return Status.complete;
-      default:
-        throw ArgumentError('Invalid status name "$name".');
-    }
-  }
-
-  const Status._(this.name);
+  factory Status.parse(String name) => Status.values.byName(name);
 
   @override
   String toString() => name;
 }
 
 /// The outcome of the test, as far as it's known.
-class Result {
+enum Result {
   /// The test has not yet failed in any way.
   ///
   /// Note that this doesn't mean that the test won't fail in the future.
-  static const success = Result._('success');
+  success,
 
   /// The test, or some part of it, has been skipped.
   ///
   /// This implies that the test hasn't failed *yet*. However, it this doesn't
   /// mean that the test won't fail in the future.
-  static const skipped = Result._('skipped');
+  skipped,
 
   /// The test has failed.
   ///
   /// A failure is specifically caused by a [TestFailure] being thrown; any
   /// other exception causes an error.
-  static const failure = Result._('failure');
+  failure,
 
   /// The test has crashed.
   ///
   /// Any exception other than a [TestFailure] is considered to be an error.
-  static const error = Result._('error');
-
-  /// The name of the result.
-  final String name;
+  error;
 
   /// Whether this is a passing result.
   ///
@@ -121,22 +102,7 @@
   /// error.
   bool get isFailing => !isPassing;
 
-  factory Result.parse(String name) {
-    switch (name) {
-      case 'success':
-        return Result.success;
-      case 'skipped':
-        return Result.skipped;
-      case 'failure':
-        return Result.failure;
-      case 'error':
-        return Result.error;
-      default:
-        throw ArgumentError('Invalid result name "$name".');
-    }
-  }
-
-  const Result._(this.name);
+  factory Result.parse(String name) => Result.values.byName(name);
 
   @override
   String toString() => name;
diff --git a/pkgs/test_api/lib/src/backend/suite_channel_manager.dart b/pkgs/test_api/lib/src/backend/suite_channel_manager.dart
index 3cd4723..26a21c9 100644
--- a/pkgs/test_api/lib/src/backend/suite_channel_manager.dart
+++ b/pkgs/test_api/lib/src/backend/suite_channel_manager.dart
@@ -20,7 +20,7 @@
   /// Creates a connection to the test runnner's channel with the given [name].
   StreamChannel<Object?> connectOut(String name) {
     if (_incomingConnections.containsKey(name)) {
-      return (_incomingConnections[name])!;
+      return _incomingConnections[name]!;
     } else if (_names.contains(name)) {
       throw StateError('Duplicate suiteChannel() connection "$name".');
     } else {
diff --git a/pkgs/test_api/lib/src/backend/suite_platform.dart b/pkgs/test_api/lib/src/backend/suite_platform.dart
index bcdb6a5..baab6ce 100644
--- a/pkgs/test_api/lib/src/backend/suite_platform.dart
+++ b/pkgs/test_api/lib/src/backend/suite_platform.dart
@@ -2,11 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'compiler.dart';
 import 'operating_system.dart';
 import 'runtime.dart';
 
 /// The platform on which a test suite is loaded.
-class SuitePlatform {
+final class SuitePlatform {
   /// The runtime that hosts the suite.
   final Runtime runtime;
 
@@ -19,16 +20,31 @@
   /// Whether we're running on Google-internal infrastructure.
   final bool inGoogle;
 
+  /// The compiler that should used for this platform.
+  final Compiler compiler;
+
   /// Creates a new platform with the given [runtime] and [os], which defaults
   /// to [OperatingSystem.none].
   ///
   /// Throws an [ArgumentError] if [runtime] is a browser and [os] is not
   /// `null` or [OperatingSystem.none].
+  ///
+  /// If [compiler] is `null`, then the default compiler for [runtime] will be
+  /// used.
   SuitePlatform(this.runtime,
-      {this.os = OperatingSystem.none, this.inGoogle = false}) {
+      {
+      // TODO(https://github.com/dart-lang/test/issues/1935): make required
+      Compiler? compiler,
+      this.os = OperatingSystem.none,
+      this.inGoogle = false})
+      : compiler = compiler ?? runtime.defaultCompiler {
     if (runtime.isBrowser && os != OperatingSystem.none) {
       throw ArgumentError('No OS should be passed for runtime "$runtime".');
     }
+    if (!runtime.supportedCompilers.contains(this.compiler)) {
+      throw ArgumentError(
+          'The platform $runtime does not support the compiler ${this.compiler}');
+    }
   }
 
   /// Converts a JSON-safe representation generated by [serialize] back into a
@@ -36,6 +52,9 @@
   factory SuitePlatform.deserialize(Object serialized) {
     var map = serialized as Map;
     return SuitePlatform(Runtime.deserialize(map['runtime'] as Object),
+        compiler: map.containsKey('compiler')
+            ? Compiler.deserialize(map['compiler'] as Object)
+            : null,
         os: OperatingSystem.find(map['os'] as String),
         inGoogle: map['inGoogle'] as bool);
   }
@@ -44,6 +63,7 @@
   /// [SuitePlatform] using [SuitePlatform.deserialize].
   Object serialize() => {
         'runtime': runtime.serialize(),
+        'compiler': compiler.serialize(),
         'os': os.identifier,
         'inGoogle': inGoogle
       };
diff --git a/pkgs/test_api/lib/src/expect/async_matcher.dart b/pkgs/test_api/lib/src/expect/async_matcher.dart
deleted file mode 100644
index a3cc965..0000000
--- a/pkgs/test_api/lib/src/expect/async_matcher.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:matcher/matcher.dart';
-import 'package:test_api/hooks.dart';
-
-import 'expect.dart';
-
-/// A matcher that does asynchronous computation.
-///
-/// Rather than implementing [matches], subclasses implement [matchAsync].
-/// [AsyncMatcher.matches] ensures that the test doesn't complete until the
-/// returned future completes, and [expect] returns a future that completes when
-/// the returned future completes so that tests can wait for it.
-abstract class AsyncMatcher extends Matcher {
-  const AsyncMatcher();
-
-  /// Returns `null` if this matches [item], or a [String] description of the
-  /// failure if it doesn't match.
-  ///
-  /// This can return a [Future] or a synchronous value. If it returns a
-  /// [Future], neither [expect] nor the test will complete until that [Future]
-  /// completes.
-  ///
-  /// If this returns a [String] synchronously, [expect] will synchronously
-  /// throw a [TestFailure] and [matches] will synchronously return `false`.
-  dynamic /*FutureOr<String>*/ matchAsync(item);
-
-  @override
-  bool matches(item, Map matchState) {
-    final result = matchAsync(item);
-    expect(result,
-        anyOf([equals(null), TypeMatcher<Future>(), TypeMatcher<String>()]),
-        reason: 'matchAsync() may only return a String, a Future, or null.');
-
-    if (result is Future) {
-      final outstandingWork = TestHandle.current.markPending();
-      result.then((realResult) {
-        if (realResult != null) {
-          fail(formatFailure(this, item, realResult as String));
-        }
-        outstandingWork.complete();
-      });
-    } else if (result is String) {
-      matchState[this] = result;
-      return false;
-    }
-
-    return true;
-  }
-
-  @override
-  Description describeMismatch(item, Description mismatchDescription,
-          Map matchState, bool verbose) =>
-      StringDescription(matchState[this] as String);
-}
diff --git a/pkgs/test_api/lib/src/expect/expect.dart b/pkgs/test_api/lib/src/expect/expect.dart
deleted file mode 100644
index 3773000..0000000
--- a/pkgs/test_api/lib/src/expect/expect.dart
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:matcher/matcher.dart';
-import 'package:test_api/hooks.dart';
-
-import 'async_matcher.dart';
-import 'util/pretty_print.dart';
-
-/// The type used for functions that can be used to build up error reports
-/// upon failures in [expect].
-@Deprecated('Will be removed in 0.13.0.')
-typedef ErrorFormatter = String Function(dynamic actual, Matcher matcher,
-    String? reason, Map matchState, bool verbose);
-
-/// Assert that [actual] matches [matcher].
-///
-/// This is the main assertion function. [reason] is optional and is typically
-/// not supplied, as a reason is generated from [matcher]; if [reason]
-/// is included it is appended to the reason generated by the matcher.
-///
-/// [matcher] can be a value in which case it will be wrapped in an
-/// [equals] matcher.
-///
-/// If the assertion fails a [TestFailure] is thrown.
-///
-/// If [skip] is a String or `true`, the assertion is skipped. The arguments are
-/// still evaluated, but [actual] is not verified to match [matcher]. If
-/// [actual] is a [Future], the test won't complete until the future emits a
-/// value.
-///
-/// If [skip] is a string, it should explain why the assertion is skipped; this
-/// reason will be printed when running the test.
-///
-/// Certain matchers, like [completion] and [throwsA], either match or fail
-/// asynchronously. When you use [expect] with these matchers, it ensures that
-/// the test doesn't complete until the matcher has either matched or failed. If
-/// you want to wait for the matcher to complete before continuing the test, you
-/// can call [expectLater] instead and `await` the result.
-void expect(actual, matcher,
-    {String? reason,
-    skip,
-    @Deprecated('Will be removed in 0.13.0.') bool verbose = false,
-    @Deprecated('Will be removed in 0.13.0.') ErrorFormatter? formatter}) {
-  _expect(actual, matcher,
-      reason: reason, skip: skip, verbose: verbose, formatter: formatter);
-}
-
-/// Just like [expect], but returns a [Future] that completes when the matcher
-/// has finished matching.
-///
-/// For the [completes] and [completion] matchers, as well as [throwsA] and
-/// related matchers when they're matched against a [Future], the returned
-/// future completes when the matched future completes. For the [prints]
-/// matcher, it completes when the future returned by the callback completes.
-/// Otherwise, it completes immediately.
-///
-/// If the matcher fails asynchronously, that failure is piped to the returned
-/// future where it can be handled by user code.
-Future expectLater(actual, matcher, {String? reason, skip}) =>
-    _expect(actual, matcher, reason: reason, skip: skip);
-
-/// The implementation of [expect] and [expectLater].
-Future _expect(actual, matcher,
-    {String? reason, skip, bool verbose = false, ErrorFormatter? formatter}) {
-  final test = TestHandle.current;
-  formatter ??= (actual, matcher, reason, matchState, verbose) {
-    var mismatchDescription = StringDescription();
-    matcher.describeMismatch(actual, mismatchDescription, matchState, verbose);
-
-    return formatFailure(matcher, actual, mismatchDescription.toString(),
-        reason: reason);
-  };
-
-  if (skip != null && skip is! bool && skip is! String) {
-    throw ArgumentError.value(skip, 'skip', 'must be a bool or a String');
-  }
-
-  matcher = wrapMatcher(matcher);
-  if (skip != null && skip != false) {
-    String message;
-    if (skip is String) {
-      message = 'Skip expect: $skip';
-    } else if (reason != null) {
-      message = 'Skip expect ($reason).';
-    } else {
-      var description = StringDescription().addDescriptionOf(matcher);
-      message = 'Skip expect ($description).';
-    }
-
-    test.markSkipped(message);
-    return Future.sync(() {});
-  }
-
-  if (matcher is AsyncMatcher) {
-    // Avoid async/await so that expect() throws synchronously when possible.
-    var result = matcher.matchAsync(actual);
-    expect(result,
-        anyOf([equals(null), TypeMatcher<Future>(), TypeMatcher<String>()]),
-        reason: 'matchAsync() may only return a String, a Future, or null.');
-
-    if (result is String) {
-      fail(formatFailure(matcher, actual, result, reason: reason));
-    } else if (result is Future) {
-      final outstandingWork = test.markPending();
-      return result.then((realResult) {
-        if (realResult == null) return;
-        fail(formatFailure(matcher as Matcher, actual, realResult as String,
-            reason: reason));
-      }).whenComplete(() {
-        // Always remove this, in case the failure is caught and handled
-        // gracefully.
-        outstandingWork.complete();
-      });
-    }
-
-    return Future.sync(() {});
-  }
-
-  var matchState = {};
-  try {
-    if ((matcher as Matcher).matches(actual, matchState)) {
-      return Future.sync(() {});
-    }
-  } catch (e, trace) {
-    reason ??= '$e at $trace';
-  }
-  fail(formatter(actual, matcher as Matcher, reason, matchState, verbose));
-}
-
-/// Convenience method for throwing a new [TestFailure] with the provided
-/// [message].
-Never fail(String message) => throw TestFailure(message);
-
-// The default error formatter.
-@Deprecated('Will be removed in 0.13.0.')
-String formatFailure(Matcher expected, actual, String which, {String? reason}) {
-  var buffer = StringBuffer();
-  buffer.writeln(indent(prettyPrint(expected), first: 'Expected: '));
-  buffer.writeln(indent(prettyPrint(actual), first: '  Actual: '));
-  if (which.isNotEmpty) buffer.writeln(indent(which, first: '   Which: '));
-  if (reason != null) buffer.writeln(reason);
-  return buffer.toString();
-}
diff --git a/pkgs/test_api/lib/src/expect/expect_async.dart b/pkgs/test_api/lib/src/expect/expect_async.dart
deleted file mode 100644
index dee7c1e..0000000
--- a/pkgs/test_api/lib/src/expect/expect_async.dart
+++ /dev/null
@@ -1,585 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test_api/hooks.dart';
-
-import 'util/placeholder.dart';
-
-// Function types returned by expectAsync# methods.
-
-typedef Func0<T> = T Function();
-typedef Func1<T, A> = T Function([A a]);
-typedef Func2<T, A, B> = T Function([A a, B b]);
-typedef Func3<T, A, B, C> = T Function([A a, B b, C c]);
-typedef Func4<T, A, B, C, D> = T Function([A a, B b, C c, D d]);
-typedef Func5<T, A, B, C, D, E> = T Function([A a, B b, C c, D d, E e]);
-typedef Func6<T, A, B, C, D, E, F> = T Function([A a, B b, C c, D d, E e, F f]);
-
-/// A wrapper for a function that ensures that it's called the appropriate
-/// number of times.
-///
-/// The containing test won't be considered to have completed successfully until
-/// this function has been called the appropriate number of times.
-///
-/// The wrapper function is accessible via [func]. It supports up to six
-/// optional and/or required positional arguments, but no named arguments.
-class _ExpectedFunction<T> {
-  /// The wrapped callback.
-  final Function _callback;
-
-  /// The minimum number of calls that are expected to be made to the function.
-  ///
-  /// If fewer calls than this are made, the test will fail.
-  final int _minExpectedCalls;
-
-  /// The maximum number of calls that are expected to be made to the function.
-  ///
-  /// If more calls than this are made, the test will fail.
-  final int _maxExpectedCalls;
-
-  /// A callback that should return whether the function is not expected to have
-  /// any more calls.
-  ///
-  /// This will be called after every time the function is run. The test case
-  /// won't be allowed to terminate until it returns `true`.
-  ///
-  /// This may be `null`. If so, the function is considered to be done after
-  /// it's been run once.
-  final bool Function()? _isDone;
-
-  /// A descriptive name for the function.
-  final String _id;
-
-  /// An optional description of why the function is expected to be called.
-  ///
-  /// If not passed, this will be an empty string.
-  final String _reason;
-
-  /// The number of times the function has been called.
-  int _actualCalls = 0;
-
-  /// The test in which this function was wrapped.
-  late final TestHandle _test;
-
-  /// Whether this function has been called the requisite number of times.
-  late bool _complete;
-
-  OutstandingWork? _outstandingWork;
-
-  /// Wraps [callback] in a function that asserts that it's called at least
-  /// [minExpected] times and no more than [maxExpected] times.
-  ///
-  /// If passed, [id] is used as a descriptive name fo the function and [reason]
-  /// as a reason it's expected to be called. If [isDone] is passed, the test
-  /// won't be allowed to complete until it returns `true`.
-  _ExpectedFunction(Function callback, int minExpected, int maxExpected,
-      {String? id, String? reason, bool Function()? isDone})
-      : _callback = callback,
-        _minExpectedCalls = minExpected,
-        _maxExpectedCalls =
-            (maxExpected == 0 && minExpected > 0) ? minExpected : maxExpected,
-        _isDone = isDone,
-        _reason = reason == null ? '' : '\n$reason',
-        _id = _makeCallbackId(id, callback) {
-    try {
-      _test = TestHandle.current;
-    } on OutsideTestException {
-      throw StateError('`expectAsync` must be called within a test.');
-    }
-
-    if (maxExpected > 0 && minExpected > maxExpected) {
-      throw ArgumentError('max ($maxExpected) may not be less than count '
-          '($minExpected).');
-    }
-
-    if (isDone != null || minExpected > 0) {
-      _outstandingWork = _test.markPending();
-      _complete = false;
-    } else {
-      _complete = true;
-    }
-  }
-
-  /// Tries to find a reasonable name for [callback].
-  ///
-  /// If [id] is passed, uses that. Otherwise, tries to determine a name from
-  /// calling `toString`. If no name can be found, returns the empty string.
-  static String _makeCallbackId(String? id, Function callback) {
-    if (id != null) return '$id ';
-
-    // If the callback is not an anonymous closure, try to get the
-    // name.
-    var toString = callback.toString();
-    var prefix = "Function '";
-    var start = toString.indexOf(prefix);
-    if (start == -1) return '';
-
-    start += prefix.length;
-    var end = toString.indexOf("'", start);
-    if (end == -1) return '';
-    return '${toString.substring(start, end)} ';
-  }
-
-  /// Returns a function that has the same number of positional arguments as the
-  /// wrapped function (up to a total of 6).
-  Function get func {
-    if (_callback is Function(Never, Never, Never, Never, Never, Never)) {
-      return max6;
-    }
-    if (_callback is Function(Never, Never, Never, Never, Never)) return max5;
-    if (_callback is Function(Never, Never, Never, Never)) return max4;
-    if (_callback is Function(Never, Never, Never)) return max3;
-    if (_callback is Function(Never, Never)) return max2;
-    if (_callback is Function(Never)) return max1;
-    if (_callback is Function()) return max0;
-
-    _outstandingWork?.complete();
-    throw ArgumentError(
-        'The wrapped function has more than 6 required arguments');
-  }
-
-  // This indirection is critical. It ensures the returned function has an
-  // argument count of zero.
-  T max0() => max6();
-
-  T max1([Object? a0 = placeholder]) => max6(a0);
-
-  T max2([Object? a0 = placeholder, Object? a1 = placeholder]) => max6(a0, a1);
-
-  T max3(
-          [Object? a0 = placeholder,
-          Object? a1 = placeholder,
-          Object? a2 = placeholder]) =>
-      max6(a0, a1, a2);
-
-  T max4(
-          [Object? a0 = placeholder,
-          Object? a1 = placeholder,
-          Object? a2 = placeholder,
-          Object? a3 = placeholder]) =>
-      max6(a0, a1, a2, a3);
-
-  T max5(
-          [Object? a0 = placeholder,
-          Object? a1 = placeholder,
-          Object? a2 = placeholder,
-          Object? a3 = placeholder,
-          Object? a4 = placeholder]) =>
-      max6(a0, a1, a2, a3, a4);
-
-  T max6(
-          [Object? a0 = placeholder,
-          Object? a1 = placeholder,
-          Object? a2 = placeholder,
-          Object? a3 = placeholder,
-          Object? a4 = placeholder,
-          Object? a5 = placeholder]) =>
-      _run([a0, a1, a2, a3, a4, a5].where((a) => a != placeholder));
-
-  /// Runs the wrapped function with [args] and returns its return value.
-  T _run(Iterable args) {
-    // Note that in the old test, this returned `null` if it encountered an
-    // error, where now it just re-throws that error because Zone machinery will
-    // pass it to the invoker anyway.
-    try {
-      _actualCalls++;
-      if (_test.shouldBeDone) {
-        throw 'Callback ${_id}called ($_actualCalls) after test case '
-            '${_test.name} had already completed.$_reason';
-      } else if (_maxExpectedCalls >= 0 && _actualCalls > _maxExpectedCalls) {
-        throw TestFailure('Callback ${_id}called more times than expected '
-            '($_maxExpectedCalls).$_reason');
-      }
-
-      return Function.apply(_callback, args.toList()) as T;
-    } finally {
-      _afterRun();
-    }
-  }
-
-  /// After each time the function is run, check to see if it's complete.
-  void _afterRun() {
-    if (_complete) return;
-    if (_minExpectedCalls > 0 && _actualCalls < _minExpectedCalls) return;
-    if (_isDone != null && !_isDone!()) return;
-
-    // Mark this callback as complete and remove it from the test case's
-    // outstanding callback count; if that hits zero the test is done.
-    _complete = true;
-    _outstandingWork?.complete();
-  }
-}
-
-/// This function is deprecated because it doesn't work well with strong mode.
-/// Use [expectAsync0], [expectAsync1],
-/// [expectAsync2], [expectAsync3], [expectAsync4], [expectAsync5], or
-/// [expectAsync6] instead.
-@Deprecated('Will be removed in 0.13.0')
-Function expectAsync(Function callback,
-        {int count = 1, int max = 0, String? id, String? reason}) =>
-    _ExpectedFunction(callback, count, max, id: id, reason: reason).func;
-
-/// Informs the framework that the given [callback] of arity 0 is expected to be
-/// called [count] number of times (by default 1).
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// The test framework will wait for the callback to run the [count] times
-/// before it considers the current test to be complete.
-///
-/// [max] can be used to specify an upper bound on the number of calls; if this
-/// is exceeded the test will fail. If [max] is `0` (the default), the callback
-/// is expected to be called exactly [count] times. If [max] is `-1`, the
-/// callback is allowed to be called any number of times greater than [count].
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with zero arguments. See also
-/// [expectAsync1], [expectAsync2], [expectAsync3], [expectAsync4],
-/// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func0<T> expectAsync0<T>(T Function() callback,
-        {int count = 1, int max = 0, String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, count, max, id: id, reason: reason).max0;
-
-/// Informs the framework that the given [callback] of arity 1 is expected to be
-/// called [count] number of times (by default 1).
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// The test framework will wait for the callback to run the [count] times
-/// before it considers the current test to be complete.
-///
-/// [max] can be used to specify an upper bound on the number of calls; if this
-/// is exceeded the test will fail. If [max] is `0` (the default), the callback
-/// is expected to be called exactly [count] times. If [max] is `-1`, the
-/// callback is allowed to be called any number of times greater than [count].
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with one argument. See also
-/// [expectAsync0], [expectAsync2], [expectAsync3], [expectAsync4],
-/// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func1<T, A> expectAsync1<T, A>(T Function(A) callback,
-        {int count = 1, int max = 0, String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, count, max, id: id, reason: reason).max1;
-
-/// Informs the framework that the given [callback] of arity 2 is expected to be
-/// called [count] number of times (by default 1).
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// The test framework will wait for the callback to run the [count] times
-/// before it considers the current test to be complete.
-///
-/// [max] can be used to specify an upper bound on the number of calls; if this
-/// is exceeded the test will fail. If [max] is `0` (the default), the callback
-/// is expected to be called exactly [count] times. If [max] is `-1`, the
-/// callback is allowed to be called any number of times greater than [count].
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with two arguments. See also
-/// [expectAsync0], [expectAsync1], [expectAsync3], [expectAsync4],
-/// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func2<T, A, B> expectAsync2<T, A, B>(T Function(A, B) callback,
-        {int count = 1, int max = 0, String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, count, max, id: id, reason: reason).max2;
-
-/// Informs the framework that the given [callback] of arity 3 is expected to be
-/// called [count] number of times (by default 1).
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// The test framework will wait for the callback to run the [count] times
-/// before it considers the current test to be complete.
-///
-/// [max] can be used to specify an upper bound on the number of calls; if this
-/// is exceeded the test will fail. If [max] is `0` (the default), the callback
-/// is expected to be called exactly [count] times. If [max] is `-1`, the
-/// callback is allowed to be called any number of times greater than [count].
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with three arguments. See also
-/// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync4],
-/// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func3<T, A, B, C> expectAsync3<T, A, B, C>(T Function(A, B, C) callback,
-        {int count = 1, int max = 0, String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, count, max, id: id, reason: reason).max3;
-
-/// Informs the framework that the given [callback] of arity 4 is expected to be
-/// called [count] number of times (by default 1).
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// The test framework will wait for the callback to run the [count] times
-/// before it considers the current test to be complete.
-///
-/// [max] can be used to specify an upper bound on the number of calls; if this
-/// is exceeded the test will fail. If [max] is `0` (the default), the callback
-/// is expected to be called exactly [count] times. If [max] is `-1`, the
-/// callback is allowed to be called any number of times greater than [count].
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with four arguments. See also
-/// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync3],
-/// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func4<T, A, B, C, D> expectAsync4<T, A, B, C, D>(
-        T Function(A, B, C, D) callback,
-        {int count = 1,
-        int max = 0,
-        String? id,
-        String? reason}) =>
-    _ExpectedFunction<T>(callback, count, max, id: id, reason: reason).max4;
-
-/// Informs the framework that the given [callback] of arity 5 is expected to be
-/// called [count] number of times (by default 1).
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// The test framework will wait for the callback to run the [count] times
-/// before it considers the current test to be complete.
-///
-/// [max] can be used to specify an upper bound on the number of calls; if this
-/// is exceeded the test will fail. If [max] is `0` (the default), the callback
-/// is expected to be called exactly [count] times. If [max] is `-1`, the
-/// callback is allowed to be called any number of times greater than [count].
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with five arguments. See also
-/// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync3],
-/// [expectAsync4], and [expectAsync6] for callbacks with different arity.
-Func5<T, A, B, C, D, E> expectAsync5<T, A, B, C, D, E>(
-        T Function(A, B, C, D, E) callback,
-        {int count = 1,
-        int max = 0,
-        String? id,
-        String? reason}) =>
-    _ExpectedFunction<T>(callback, count, max, id: id, reason: reason).max5;
-
-/// Informs the framework that the given [callback] of arity 6 is expected to be
-/// called [count] number of times (by default 1).
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// The test framework will wait for the callback to run the [count] times
-/// before it considers the current test to be complete.
-///
-/// [max] can be used to specify an upper bound on the number of calls; if this
-/// is exceeded the test will fail. If [max] is `0` (the default), the callback
-/// is expected to be called exactly [count] times. If [max] is `-1`, the
-/// callback is allowed to be called any number of times greater than [count].
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with six arguments. See also
-/// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync3],
-/// [expectAsync4], and [expectAsync5] for callbacks with different arity.
-Func6<T, A, B, C, D, E, F> expectAsync6<T, A, B, C, D, E, F>(
-        T Function(A, B, C, D, E, F) callback,
-        {int count = 1,
-        int max = 0,
-        String? id,
-        String? reason}) =>
-    _ExpectedFunction<T>(callback, count, max, id: id, reason: reason).max6;
-
-/// This function is deprecated because it doesn't work well with strong mode.
-/// Use [expectAsyncUntil0], [expectAsyncUntil1],
-/// [expectAsyncUntil2], [expectAsyncUntil3], [expectAsyncUntil4],
-/// [expectAsyncUntil5], or [expectAsyncUntil6] instead.
-@Deprecated('Will be removed in 0.13.0')
-Function expectAsyncUntil(Function callback, bool Function() isDone,
-        {String? id, String? reason}) =>
-    _ExpectedFunction(callback, 0, -1, id: id, reason: reason, isDone: isDone)
-        .func;
-
-/// Informs the framework that the given [callback] of arity 0 is expected to be
-/// called until [isDone] returns true.
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// [isDone] is called after each time the function is run. Only when it returns
-/// true will the callback be considered complete.
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with zero arguments. See also
-/// [expectAsyncUntil1], [expectAsyncUntil2], [expectAsyncUntil3],
-/// [expectAsyncUntil4], [expectAsyncUntil5], and [expectAsyncUntil6] for
-/// callbacks with different arity.
-Func0<T> expectAsyncUntil0<T>(T Function() callback, bool Function() isDone,
-        {String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, 0, -1,
-            id: id, reason: reason, isDone: isDone)
-        .max0;
-
-/// Informs the framework that the given [callback] of arity 1 is expected to be
-/// called until [isDone] returns true.
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// [isDone] is called after each time the function is run. Only when it returns
-/// true will the callback be considered complete.
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with one argument. See also
-/// [expectAsyncUntil0], [expectAsyncUntil2], [expectAsyncUntil3],
-/// [expectAsyncUntil4], [expectAsyncUntil5], and [expectAsyncUntil6] for
-/// callbacks with different arity.
-Func1<T, A> expectAsyncUntil1<T, A>(
-        T Function(A) callback, bool Function() isDone,
-        {String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, 0, -1,
-            id: id, reason: reason, isDone: isDone)
-        .max1;
-
-/// Informs the framework that the given [callback] of arity 2 is expected to be
-/// called until [isDone] returns true.
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// [isDone] is called after each time the function is run. Only when it returns
-/// true will the callback be considered complete.
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with two arguments. See also
-/// [expectAsyncUntil0], [expectAsyncUntil1], [expectAsyncUntil3],
-/// [expectAsyncUntil4], [expectAsyncUntil5], and [expectAsyncUntil6] for
-/// callbacks with different arity.
-Func2<T, A, B> expectAsyncUntil2<T, A, B>(
-        T Function(A, B) callback, bool Function() isDone,
-        {String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, 0, -1,
-            id: id, reason: reason, isDone: isDone)
-        .max2;
-
-/// Informs the framework that the given [callback] of arity 3 is expected to be
-/// called until [isDone] returns true.
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// [isDone] is called after each time the function is run. Only when it returns
-/// true will the callback be considered complete.
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with three arguments. See also
-/// [expectAsyncUntil0], [expectAsyncUntil1], [expectAsyncUntil2],
-/// [expectAsyncUntil4], [expectAsyncUntil5], and [expectAsyncUntil6] for
-/// callbacks with different arity.
-Func3<T, A, B, C> expectAsyncUntil3<T, A, B, C>(
-        T Function(A, B, C) callback, bool Function() isDone,
-        {String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, 0, -1,
-            id: id, reason: reason, isDone: isDone)
-        .max3;
-
-/// Informs the framework that the given [callback] of arity 4 is expected to be
-/// called until [isDone] returns true.
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// [isDone] is called after each time the function is run. Only when it returns
-/// true will the callback be considered complete.
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with four arguments. See also
-/// [expectAsyncUntil0], [expectAsyncUntil1], [expectAsyncUntil2],
-/// [expectAsyncUntil3], [expectAsyncUntil5], and [expectAsyncUntil6] for
-/// callbacks with different arity.
-Func4<T, A, B, C, D> expectAsyncUntil4<T, A, B, C, D>(
-        T Function(A, B, C, D) callback, bool Function() isDone,
-        {String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, 0, -1,
-            id: id, reason: reason, isDone: isDone)
-        .max4;
-
-/// Informs the framework that the given [callback] of arity 5 is expected to be
-/// called until [isDone] returns true.
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// [isDone] is called after each time the function is run. Only when it returns
-/// true will the callback be considered complete.
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with five arguments. See also
-/// [expectAsyncUntil0], [expectAsyncUntil1], [expectAsyncUntil2],
-/// [expectAsyncUntil3], [expectAsyncUntil4], and [expectAsyncUntil6] for
-/// callbacks with different arity.
-Func5<T, A, B, C, D, E> expectAsyncUntil5<T, A, B, C, D, E>(
-        T Function(A, B, C, D, E) callback, bool Function() isDone,
-        {String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, 0, -1,
-            id: id, reason: reason, isDone: isDone)
-        .max5;
-
-/// Informs the framework that the given [callback] of arity 6 is expected to be
-/// called until [isDone] returns true.
-///
-/// Returns a wrapped function that should be used as a replacement of the
-/// original callback.
-///
-/// [isDone] is called after each time the function is run. Only when it returns
-/// true will the callback be considered complete.
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-///
-/// This method takes callbacks with six arguments. See also
-/// [expectAsyncUntil0], [expectAsyncUntil1], [expectAsyncUntil2],
-/// [expectAsyncUntil3], [expectAsyncUntil4], and [expectAsyncUntil5] for
-/// callbacks with different arity.
-Func6<T, A, B, C, D, E, F> expectAsyncUntil6<T, A, B, C, D, E, F>(
-        T Function(A, B, C, D, E, F) callback, bool Function() isDone,
-        {String? id, String? reason}) =>
-    _ExpectedFunction<T>(callback, 0, -1,
-            id: id, reason: reason, isDone: isDone)
-        .max6;
diff --git a/pkgs/test_api/lib/src/expect/future_matchers.dart b/pkgs/test_api/lib/src/expect/future_matchers.dart
deleted file mode 100644
index 9900c97..0000000
--- a/pkgs/test_api/lib/src/expect/future_matchers.dart
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:matcher/matcher.dart';
-import 'package:test_api/hooks.dart' show pumpEventQueue;
-
-import 'async_matcher.dart';
-import 'expect.dart';
-import 'util/pretty_print.dart';
-
-/// Matches a [Future] that completes successfully with any value.
-///
-/// This creates an asynchronous expectation. The call to [expect] will return
-/// immediately and execution will continue. Later, when the future completes,
-/// the expectation against [matcher] will run. To wait for the future to
-/// complete and the expectation to run use [expectLater] and wait on the
-/// returned future.
-///
-/// To test that a Future completes with an exception, you can use [throws] and
-/// [throwsA].
-final Matcher completes = const _Completes(null);
-
-/// Matches a [Future] that completes successfully with a value that matches
-/// [matcher].
-///
-/// This creates an asynchronous expectation. The call to [expect] will return
-/// immediately and execution will continue. Later, when the future completes,
-/// the expectation against [matcher] will run. To wait for the future to
-/// complete and the expectation to run use [expectLater] and wait on the
-/// returned future.
-///
-/// To test that a Future completes with an exception, you can use [throws] and
-/// [throwsA].
-Matcher completion(matcher,
-        [@Deprecated('this parameter is ignored') String? description]) =>
-    _Completes(wrapMatcher(matcher));
-
-class _Completes extends AsyncMatcher {
-  final Matcher? _matcher;
-
-  const _Completes(this._matcher);
-
-  // Avoid async/await so we synchronously start listening to [item].
-  @override
-  dynamic /*FutureOr<String>*/ matchAsync(item) {
-    if (item is! Future) return 'was not a Future';
-
-    return item.then((value) async {
-      if (_matcher == null) return null;
-
-      String? result;
-      if (_matcher is AsyncMatcher) {
-        result = await (_matcher as AsyncMatcher).matchAsync(value) as String?;
-        if (result == null) return null;
-      } else {
-        var matchState = {};
-        if (_matcher!.matches(value, matchState)) return null;
-        result = _matcher!
-            .describeMismatch(value, StringDescription(), matchState, false)
-            .toString();
-      }
-
-      var buffer = StringBuffer();
-      buffer.writeln(indent(prettyPrint(value), first: 'emitted '));
-      if (result.isNotEmpty) buffer.writeln(indent(result, first: '  which '));
-      return buffer.toString().trimRight();
-    });
-  }
-
-  @override
-  Description describe(Description description) {
-    if (_matcher == null) {
-      description.add('completes successfully');
-    } else {
-      description.add('completes to a value that ').addDescriptionOf(_matcher);
-    }
-    return description;
-  }
-}
-
-/// Matches a [Future] that does not complete.
-///
-/// Note that this creates an asynchronous expectation. The call to
-/// `expect()` that includes this will return immediately and execution will
-/// continue.
-final Matcher doesNotComplete = const _DoesNotComplete();
-
-class _DoesNotComplete extends Matcher {
-  const _DoesNotComplete();
-
-  @override
-  Description describe(Description description) {
-    description.add('does not complete');
-    return description;
-  }
-
-  @override
-  bool matches(item, Map matchState) {
-    if (item is! Future) return false;
-    item.then((value) {
-      fail('Future was not expected to complete but completed with a value of '
-          '$value');
-    });
-    expect(pumpEventQueue(), completes);
-    return true;
-  }
-
-  @override
-  Description describeMismatch(
-      item, Description description, Map matchState, bool verbose) {
-    if (item is! Future) return description.add('$item is not a Future');
-    return description;
-  }
-}
diff --git a/pkgs/test_api/lib/src/expect/never_called.dart b/pkgs/test_api/lib/src/expect/never_called.dart
deleted file mode 100644
index 96c81cb..0000000
--- a/pkgs/test_api/lib/src/expect/never_called.dart
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:stack_trace/stack_trace.dart';
-import 'package:test_api/hooks.dart';
-
-import 'expect.dart';
-import 'future_matchers.dart';
-import 'util/placeholder.dart';
-import 'util/pretty_print.dart';
-
-/// Returns a function that causes the test to fail if it's called.
-///
-/// This can safely be passed in place of any callback that takes ten or fewer
-/// positional parameters. For example:
-///
-/// ```
-/// // Asserts that the stream never emits an event.
-/// stream.listen(neverCalled);
-/// ```
-///
-/// This also ensures that the test doesn't complete until a call to
-/// [pumpEventQueue] finishes, so that the callback has a chance to be called.
-Null Function(
-    [Object?,
-    Object?,
-    Object?,
-    Object?,
-    Object?,
-    Object?,
-    Object?,
-    Object?,
-    Object?,
-    Object?]) get neverCalled {
-  // Make sure the test stays alive long enough to call the function if it's
-  // going to.
-  expect(pumpEventQueue(), completes);
-
-  var zone = Zone.current;
-  return (
-      [a1 = placeholder,
-      a2 = placeholder,
-      a3 = placeholder,
-      a4 = placeholder,
-      a5 = placeholder,
-      a6 = placeholder,
-      a7 = placeholder,
-      a8 = placeholder,
-      a9 = placeholder,
-      a10 = placeholder]) {
-    var arguments = [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]
-        .where((argument) => argument != placeholder)
-        .toList();
-
-    var argsText = arguments.isEmpty
-        ? ' no arguments.'
-        : ':\n${bullet(arguments.map(prettyPrint))}';
-    zone.handleUncaughtError(
-        TestFailure(
-            'Callback should never have been called, but it was called with'
-            '$argsText'),
-        zone.run(() => Chain.current()));
-    return null;
-  };
-}
diff --git a/pkgs/test_api/lib/src/expect/prints_matcher.dart b/pkgs/test_api/lib/src/expect/prints_matcher.dart
deleted file mode 100644
index 5e9769b..0000000
--- a/pkgs/test_api/lib/src/expect/prints_matcher.dart
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:matcher/matcher.dart';
-
-import 'async_matcher.dart';
-import 'expect.dart';
-import 'util/pretty_print.dart';
-
-/// Matches a [Function] that prints text that matches [matcher].
-///
-/// [matcher] may be a String or a [Matcher].
-///
-/// If the function this runs against returns a [Future], all text printed by
-/// the function (using [Zone] scoping) until that Future completes is matched.
-///
-/// This only tracks text printed using the [print] function.
-///
-/// This returns an [AsyncMatcher], so [expect] won't complete until the matched
-/// function does.
-Matcher prints(matcher) => _Prints(wrapMatcher(matcher));
-
-class _Prints extends AsyncMatcher {
-  final Matcher _matcher;
-
-  _Prints(this._matcher);
-
-  // Avoid async/await so we synchronously fail if the function is
-  // synchronous.
-  @override
-  dynamic /*FutureOr<String>*/ matchAsync(item) {
-    if (item is! Function()) return 'was not a unary Function';
-
-    var buffer = StringBuffer();
-    var result = runZoned(item,
-        zoneSpecification: ZoneSpecification(print: (_, __, ____, line) {
-      buffer.writeln(line);
-    }));
-
-    return result is Future
-        ? result.then((_) => _check(buffer.toString()))
-        : _check(buffer.toString());
-  }
-
-  @override
-  Description describe(Description description) =>
-      description.add('prints ').addDescriptionOf(_matcher);
-
-  /// Verifies that [actual] matches [_matcher] and returns a [String]
-  /// description of the failure if it doesn't.
-  String? _check(String actual) {
-    var matchState = {};
-    if (_matcher.matches(actual, matchState)) return null;
-
-    var result = _matcher
-        .describeMismatch(actual, StringDescription(), matchState, false)
-        .toString();
-
-    var buffer = StringBuffer();
-    if (actual.isEmpty) {
-      buffer.writeln('printed nothing');
-    } else {
-      buffer.writeln(indent(prettyPrint(actual), first: 'printed '));
-    }
-    if (result.isNotEmpty) buffer.writeln(indent(result, first: '  which '));
-    return buffer.toString().trimRight();
-  }
-}
diff --git a/pkgs/test_api/lib/src/expect/stream_matcher.dart b/pkgs/test_api/lib/src/expect/stream_matcher.dart
deleted file mode 100644
index 6d7bddf..0000000
--- a/pkgs/test_api/lib/src/expect/stream_matcher.dart
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:async/async.dart';
-import 'package:matcher/matcher.dart';
-import 'package:test_api/hooks.dart';
-
-import 'async_matcher.dart';
-import 'util/pretty_print.dart';
-
-/// A matcher that matches events from [Stream]s or [StreamQueue]s.
-///
-/// Stream matchers are designed to make it straightforward to create complex
-/// expectations for streams, and to interleave expectations with the rest of a
-/// test. They can be used on a [Stream] to match all events it emits:
-///
-/// ```dart
-/// expect(stream, emitsInOrder([
-///   // Values match individual events.
-///   "Ready.",
-///
-///   // Matchers also run against individual events.
-///   startsWith("Loading took"),
-///
-///   // Stream matchers can be nested. This asserts that one of two events are
-///   // emitted after the "Loading took" line.
-///   emitsAnyOf(["Succeeded!", "Failed!"]),
-///
-///   // By default, more events are allowed after the matcher finishes
-///   // matching. This asserts instead that the stream emits a done event and
-///   // nothing else.
-///   emitsDone
-/// ]));
-/// ```
-///
-/// It can also match a [StreamQueue], in which case it consumes the matched
-/// events. The call to [expect] returns a [Future] that completes when the
-/// matcher is done matching. You can `await` this to consume different events
-/// at different times:
-///
-/// ```dart
-/// var stdout = StreamQueue(stdoutLineStream);
-///
-/// // Ignore lines from the process until it's about to emit the URL.
-/// await expectLater(stdout, emitsThrough('WebSocket URL:'));
-///
-/// // Parse the next line as a URL.
-/// var url = Uri.parse(await stdout.next);
-/// expect(url.host, equals('localhost'));
-///
-/// // You can match against the same StreamQueue multiple times.
-/// await expectLater(stdout, emits('Waiting for connection...'));
-/// ```
-///
-/// Users can call [StreamMatcher] to create custom matchers.
-abstract class StreamMatcher extends Matcher {
-  /// The description of this matcher.
-  ///
-  /// This is in the subjunctive mood, which means it can be used after the word
-  /// "should". For example, it might be "emit the right events".
-  String get description;
-
-  /// Creates a new [StreamMatcher] described by [description] that matches
-  /// events with [matchQueue].
-  ///
-  /// The [matchQueue] callback is used to implement [StreamMatcher.matchQueue],
-  /// and should follow all the guarantees of that method. In particular:
-  ///
-  /// * If it matches successfully, it should return `null` and possibly consume
-  ///   events.
-  /// * If it fails to match, consume no events and return a description of the
-  ///   failure.
-  /// * The description should be in past tense.
-  /// * The description should be grammatically valid when used after "the
-  ///   stream"—"emitted the wrong events", for example.
-  ///
-  /// The [matchQueue] callback may return the empty string to indicate a
-  /// failure if it has no information to add beyond the description of the
-  /// failure and the events actually emitted by the stream.
-  ///
-  /// The [description] should be in the subjunctive mood. This means that it
-  /// should be grammatically valid when used after the word "should". For
-  /// example, it might be "emit the right events".
-  factory StreamMatcher(Future<String?> Function(StreamQueue) matchQueue,
-      String description) = _StreamMatcher;
-
-  /// Tries to match events emitted by [queue].
-  ///
-  /// If this matches successfully, it consumes the matching events from [queue]
-  /// and returns `null`.
-  ///
-  /// If this fails to match, it doesn't consume any events and returns a
-  /// description of the failure. This description is in the past tense, and
-  /// could grammatically be used after "the stream". For example, it might
-  /// return "emitted the wrong events".
-  ///
-  /// The description string may also be empty, which indicates that the
-  /// matcher's description and the events actually emitted by the stream are
-  /// enough to understand the failure.
-  ///
-  /// If the queue emits an error, that error is re-thrown unless otherwise
-  /// indicated by the matcher.
-  Future<String?> matchQueue(StreamQueue queue);
-}
-
-/// A concrete implementation of [StreamMatcher].
-///
-/// This is separate from the original type to hide the private [AsyncMatcher]
-/// interface.
-class _StreamMatcher extends AsyncMatcher implements StreamMatcher {
-  @override
-  final String description;
-
-  /// The callback used to implement [matchQueue].
-  final Future<String?> Function(StreamQueue) _matchQueue;
-
-  _StreamMatcher(this._matchQueue, this.description);
-
-  @override
-  Future<String?> matchQueue(StreamQueue queue) => _matchQueue(queue);
-
-  @override
-  dynamic /*FutureOr<String>*/ matchAsync(item) {
-    StreamQueue queue;
-    var shouldCancelQueue = false;
-    if (item is StreamQueue) {
-      queue = item;
-    } else if (item is Stream) {
-      queue = StreamQueue(item);
-      shouldCancelQueue = true;
-    } else {
-      return 'was not a Stream or a StreamQueue';
-    }
-
-    // Avoid async/await in the outer method so that we synchronously error out
-    // for an invalid argument type.
-    var transaction = queue.startTransaction();
-    var copy = transaction.newQueue();
-    return matchQueue(copy).then((result) async {
-      // Accept the transaction if the result is null, indicating that the match
-      // succeeded.
-      if (result == null) {
-        transaction.commit(copy);
-        return null;
-      }
-
-      // Get a list of events emitted by the stream so we can emit them as part
-      // of the error message.
-      var replay = transaction.newQueue();
-      var events = <Result?>[];
-      var subscription = Result.captureStreamTransformer
-          .bind(replay.rest.cast())
-          .listen(events.add, onDone: () => events.add(null));
-
-      // Wait on a timer tick so all buffered events are emitted.
-      await Future.delayed(Duration.zero);
-      _unawaited(subscription.cancel());
-
-      var eventsString = events.map((event) {
-        if (event == null) {
-          return 'x Stream closed.';
-        } else if (event.isValue) {
-          return addBullet(event.asValue!.value.toString());
-        } else {
-          var error = event.asError!;
-          var chain = TestHandle.current.formatStackTrace(error.stackTrace);
-          var text = '${error.error}\n$chain';
-          return indent(text, first: '! ');
-        }
-      }).join('\n');
-      if (eventsString.isEmpty) eventsString = 'no events';
-
-      transaction.reject();
-
-      var buffer = StringBuffer();
-      buffer.writeln(indent(eventsString, first: 'emitted '));
-      if (result.isNotEmpty) buffer.writeln(indent(result, first: '  which '));
-      return buffer.toString().trimRight();
-    }, onError: (Object error) {
-      transaction.reject();
-      throw error;
-    }).then((result) {
-      if (shouldCancelQueue) queue.cancel();
-      return result;
-    });
-  }
-
-  @override
-  Description describe(Description description) =>
-      description.add('should ').add(this.description);
-}
-
-void _unawaited(Future<void> f) {}
diff --git a/pkgs/test_api/lib/src/expect/stream_matchers.dart b/pkgs/test_api/lib/src/expect/stream_matchers.dart
deleted file mode 100644
index df2fbbd..0000000
--- a/pkgs/test_api/lib/src/expect/stream_matchers.dart
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:async/async.dart';
-import 'package:matcher/matcher.dart';
-
-import 'async_matcher.dart';
-import 'stream_matcher.dart';
-import 'throws_matcher.dart';
-import 'util/pretty_print.dart';
-
-/// Returns a [StreamMatcher] that asserts that the stream emits a "done" event.
-final emitsDone = StreamMatcher(
-    (queue) async => (await queue.hasNext) ? '' : null, 'be done');
-
-/// Returns a [StreamMatcher] for [matcher].
-///
-/// If [matcher] is already a [StreamMatcher], it's returned as-is. If it's any
-/// other [Matcher], this matches a single event that matches that matcher. If
-/// it's any other Object, this matches a single event that's equal to that
-/// object.
-///
-/// This functions like [wrapMatcher] for [StreamMatcher]s: it can convert any
-/// matcher-like value into a proper [StreamMatcher].
-StreamMatcher emits(matcher) {
-  if (matcher is StreamMatcher) return matcher;
-  var wrapped = wrapMatcher(matcher);
-
-  var matcherDescription = wrapped.describe(StringDescription());
-
-  return StreamMatcher((queue) async {
-    if (!await queue.hasNext) return '';
-
-    var matchState = {};
-    var actual = await queue.next;
-    if (wrapped.matches(actual, matchState)) return null;
-
-    var mismatchDescription = StringDescription();
-    wrapped.describeMismatch(actual, mismatchDescription, matchState, false);
-
-    if (mismatchDescription.length == 0) return '';
-    return 'emitted an event that $mismatchDescription';
-  },
-      // TODO(nweiz): add "should" once matcher#42 is fixed.
-      'emit an event that $matcherDescription');
-}
-
-/// Returns a [StreamMatcher] that matches a single error event that matches
-/// [matcher].
-StreamMatcher emitsError(matcher) {
-  var wrapped = wrapMatcher(matcher);
-  var matcherDescription = wrapped.describe(StringDescription());
-  var throwsMatcher = throwsA(wrapped) as AsyncMatcher;
-
-  return StreamMatcher(
-      (queue) => throwsMatcher.matchAsync(queue.next) as Future<String?>,
-      // TODO(nweiz): add "should" once matcher#42 is fixed.
-      'emit an error that $matcherDescription');
-}
-
-/// Returns a [StreamMatcher] that allows (but doesn't require) [matcher] to
-/// match the stream.
-///
-/// This matcher always succeeds; if [matcher] doesn't match, this just consumes
-/// no events.
-StreamMatcher mayEmit(matcher) {
-  var streamMatcher = emits(matcher);
-  return StreamMatcher((queue) async {
-    await queue.withTransaction(
-        (copy) async => (await streamMatcher.matchQueue(copy)) == null);
-    return null;
-  }, 'maybe ${streamMatcher.description}');
-}
-
-/// Returns a [StreamMatcher] that matches the stream if at least one of
-/// [matchers] matches.
-///
-/// If multiple matchers match the stream, this chooses the matcher that
-/// consumes as many events as possible.
-///
-/// If any matchers match the stream, no errors from other matchers are thrown.
-/// If no matchers match and multiple matchers threw errors, the first error is
-/// re-thrown.
-StreamMatcher emitsAnyOf(Iterable matchers) {
-  var streamMatchers = matchers.map(emits).toList();
-  if (streamMatchers.isEmpty) {
-    throw ArgumentError('matcher may not be empty');
-  }
-
-  if (streamMatchers.length == 1) return streamMatchers.first;
-  var description = 'do one of the following:\n'
-      '${bullet(streamMatchers.map((matcher) => matcher.description))}';
-
-  return StreamMatcher((queue) async {
-    var transaction = queue.startTransaction();
-
-    // Allocate the failures list ahead of time so that its order matches the
-    // order of [matchers], and thus the order the matchers will be listed in
-    // the description.
-    var failures = List<String?>.filled(matchers.length, null);
-
-    // The first error thrown. If no matchers match and this exists, we rethrow
-    // it.
-    Object? firstError;
-    StackTrace? firstStackTrace;
-
-    var futures = <Future>[];
-    StreamQueue? consumedMost;
-    for (var i = 0; i < matchers.length; i++) {
-      futures.add(() async {
-        var copy = transaction.newQueue();
-
-        String? result;
-        try {
-          result = await streamMatchers[i].matchQueue(copy);
-        } catch (error, stackTrace) {
-          if (firstError == null) {
-            firstError = error;
-            firstStackTrace = stackTrace;
-          }
-          return;
-        }
-
-        if (result != null) {
-          failures[i] = result;
-        } else if (consumedMost == null ||
-            consumedMost!.eventsDispatched < copy.eventsDispatched) {
-          consumedMost = copy;
-        }
-      }());
-    }
-
-    await Future.wait(futures);
-
-    if (consumedMost == null) {
-      transaction.reject();
-      if (firstError != null) {
-        await Future.error(firstError!, firstStackTrace);
-      }
-
-      var failureMessages = <String>[];
-      for (var i = 0; i < matchers.length; i++) {
-        var message = 'failed to ${streamMatchers[i].description}';
-        if ((failures[i])!.isNotEmpty) {
-          message += message.contains('\n') ? '\n' : ' ';
-          message += 'because it ${failures[i]}';
-        }
-
-        failureMessages.add(message);
-      }
-
-      return 'failed all options:\n${bullet(failureMessages)}';
-    } else {
-      transaction.commit(consumedMost!);
-      return null;
-    }
-  }, description);
-}
-
-/// Returns a [StreamMatcher] that matches the stream if each matcher in
-/// [matchers] matches, one after another.
-///
-/// If any matcher fails to match, this fails and consumes no events.
-StreamMatcher emitsInOrder(Iterable matchers) {
-  var streamMatchers = matchers.map(emits).toList();
-  if (streamMatchers.length == 1) return streamMatchers.first;
-
-  var description = 'do the following in order:\n'
-      '${bullet(streamMatchers.map((matcher) => matcher.description))}';
-
-  return StreamMatcher((queue) async {
-    for (var i = 0; i < streamMatchers.length; i++) {
-      var matcher = streamMatchers[i];
-      var result = await matcher.matchQueue(queue);
-      if (result == null) continue;
-
-      var newResult = "didn't ${matcher.description}";
-      if (result.isNotEmpty) {
-        newResult += newResult.contains('\n') ? '\n' : ' ';
-        newResult += 'because it $result';
-      }
-      return newResult;
-    }
-    return null;
-  }, description);
-}
-
-/// Returns a [StreamMatcher] that matches any number of events followed by
-/// events that match [matcher].
-///
-/// This consumes all events matched by [matcher], as well as all events before.
-/// If the stream emits a done event without matching [matcher], this fails and
-/// consumes no events.
-StreamMatcher emitsThrough(matcher) {
-  var streamMatcher = emits(matcher);
-  return StreamMatcher((queue) async {
-    var failures = <String>[];
-
-    Future<bool> tryHere() => queue.withTransaction((copy) async {
-          var result = await streamMatcher.matchQueue(copy);
-          if (result == null) return true;
-          failures.add(result);
-          return false;
-        });
-
-    while (await queue.hasNext) {
-      if (await tryHere()) return null;
-      await queue.next;
-    }
-
-    // Try after the queue is done in case the matcher can match an empty
-    // stream.
-    if (await tryHere()) return null;
-
-    var result = 'never did ${streamMatcher.description}';
-
-    var failureMessages =
-        bullet(failures.where((failure) => failure.isNotEmpty));
-    if (failureMessages.isNotEmpty) {
-      result += result.contains('\n') ? '\n' : ' ';
-      result += 'because it:\n$failureMessages';
-    }
-
-    return result;
-  }, 'eventually ${streamMatcher.description}');
-}
-
-/// Returns a [StreamMatcher] that matches any number of events that match
-/// [matcher].
-///
-/// This consumes events until [matcher] no longer matches. It always succeeds;
-/// if [matcher] doesn't match, this just consumes no events. It never rethrows
-/// errors.
-StreamMatcher mayEmitMultiple(matcher) {
-  var streamMatcher = emits(matcher);
-
-  var description = streamMatcher.description;
-  description += description.contains('\n') ? '\n' : ' ';
-  description += 'zero or more times';
-
-  return StreamMatcher((queue) async {
-    while (await _tryMatch(queue, streamMatcher)) {
-      // Do nothing; the matcher presumably already consumed events.
-    }
-    return null;
-  }, description);
-}
-
-/// Returns a [StreamMatcher] that matches a stream that never matches
-/// [matcher].
-///
-/// This doesn't complete until the stream emits a done event. It never consumes
-/// any events. It never re-throws errors.
-StreamMatcher neverEmits(matcher) {
-  var streamMatcher = emits(matcher);
-  return StreamMatcher((queue) async {
-    var events = 0;
-    var matched = false;
-    await queue.withTransaction((copy) async {
-      while (await copy.hasNext) {
-        matched = await _tryMatch(copy, streamMatcher);
-        if (matched) return false;
-
-        events++;
-
-        try {
-          await copy.next;
-        } catch (_) {
-          // Ignore errors events.
-        }
-      }
-
-      matched = await _tryMatch(copy, streamMatcher);
-      return false;
-    });
-
-    if (!matched) return null;
-    return "after $events ${pluralize('event', events)} did "
-        '${streamMatcher.description}';
-  }, 'never ${streamMatcher.description}');
-}
-
-/// Returns whether [matcher] matches [queue] at its current position.
-///
-/// This treats errors as failures to match.
-Future<bool> _tryMatch(StreamQueue queue, StreamMatcher matcher) {
-  return queue.withTransaction((copy) async {
-    try {
-      return (await matcher.matchQueue(copy)) == null;
-    } catch (_) {
-      return false;
-    }
-  });
-}
-
-/// Returns a [StreamMatcher] that matches the stream if each matcher in
-/// [matchers] matches, in any order.
-///
-/// If any matcher fails to match, this fails and consumes no events. If the
-/// matchers match in multiple different possible orders, this chooses the order
-/// that consumes as many events as possible.
-///
-/// If any sequence of matchers matches the stream, no errors from other
-/// sequences are thrown. If no sequences match and multiple sequences throw
-/// errors, the first error is re-thrown.
-///
-/// Note that checking every ordering of [matchers] is O(n!) in the worst case,
-/// so this should only be called when there are very few [matchers].
-StreamMatcher emitsInAnyOrder(Iterable matchers) {
-  var streamMatchers = matchers.map(emits).toSet();
-  if (streamMatchers.length == 1) return streamMatchers.first;
-  var description = 'do the following in any order:\n'
-      '${bullet(streamMatchers.map((matcher) => matcher.description))}';
-
-  return StreamMatcher(
-      (queue) async => await _tryInAnyOrder(queue, streamMatchers) ? null : '',
-      description);
-}
-
-/// Returns whether [queue] matches [matchers] in any order.
-Future<bool> _tryInAnyOrder(
-    StreamQueue queue, Set<StreamMatcher> matchers) async {
-  if (matchers.length == 1) {
-    return await matchers.first.matchQueue(queue) == null;
-  }
-
-  var transaction = queue.startTransaction();
-  StreamQueue? consumedMost;
-
-  // The first error thrown. If no matchers match and this exists, we rethrow
-  // it.
-  Object? firstError;
-  StackTrace? firstStackTrace;
-
-  await Future.wait(matchers.map((matcher) async {
-    var copy = transaction.newQueue();
-    try {
-      if (await matcher.matchQueue(copy) != null) return;
-    } catch (error, stackTrace) {
-      if (firstError == null) {
-        firstError = error;
-        firstStackTrace = stackTrace;
-      }
-      return;
-    }
-
-    var rest = Set<StreamMatcher>.from(matchers);
-    rest.remove(matcher);
-
-    try {
-      if (!await _tryInAnyOrder(copy, rest)) return;
-    } catch (error, stackTrace) {
-      if (firstError == null) {
-        firstError = error;
-        firstStackTrace = stackTrace;
-      }
-      return;
-    }
-
-    if (consumedMost == null ||
-        consumedMost!.eventsDispatched < copy.eventsDispatched) {
-      consumedMost = copy;
-    }
-  }));
-
-  if (consumedMost == null) {
-    transaction.reject();
-    if (firstError != null) await Future.error(firstError!, firstStackTrace);
-    return false;
-  } else {
-    transaction.commit(consumedMost!);
-    return true;
-  }
-}
diff --git a/pkgs/test_api/lib/src/expect/throws_matcher.dart b/pkgs/test_api/lib/src/expect/throws_matcher.dart
deleted file mode 100644
index b4f081e..0000000
--- a/pkgs/test_api/lib/src/expect/throws_matcher.dart
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:matcher/matcher.dart';
-import 'package:test_api/hooks.dart';
-
-import 'async_matcher.dart';
-import 'util/pretty_print.dart';
-
-/// This function is deprecated.
-///
-/// Use [throwsA] instead. We strongly recommend that you add assertions about
-/// at least the type of the error, but you can write `throwsA(anything)` to
-/// mimic the behavior of this matcher.
-@Deprecated('Will be removed in 0.13.0')
-const Matcher throws = Throws();
-
-/// This can be used to match three kinds of objects:
-///
-/// * A [Function] that throws an exception when called. The function cannot
-///   take any arguments. If you want to test that a function expecting
-///   arguments throws, wrap it in another zero-argument function that calls
-///   the one you want to test.
-///
-/// * A [Future] that completes with an exception. Note that this creates an
-///   asynchronous expectation. The call to `expect()` that includes this will
-///   return immediately and execution will continue. Later, when the future
-///   completes, the actual expectation will run.
-///
-/// * A [Function] that returns a [Future] that completes with an exception.
-///
-/// In all three cases, when an exception is thrown, this will test that the
-/// exception object matches [matcher]. If [matcher] is not an instance of
-/// [Matcher], it will implicitly be treated as `equals(matcher)`.
-///
-/// Examples:
-/// ```dart
-/// void functionThatThrows() => throw SomeException();
-///
-/// void functionWithArgument(bool shouldThrow) {
-///   if (shouldThrow) {
-///     throw SomeException();
-///   }
-/// }
-///
-/// Future<void> asyncFunctionThatThrows() async => throw SomeException();
-///
-/// expect(functionThatThrows, throwsA(isA<SomeException>()));
-///
-/// expect(() => functionWithArgument(true), throwsA(isA<SomeException>()));
-///
-/// var future = asyncFunctionThatThrows();
-/// await expectLater(future, throwsA(isA<SomeException>()));
-///
-/// await expectLater(
-///     asyncFunctionThatThrows, throwsA(isA<SomeException>()));
-/// ```
-Matcher throwsA(matcher) => Throws(wrapMatcher(matcher));
-
-/// Use the [throwsA] function instead.
-@Deprecated('Will be removed in 0.13.0')
-class Throws extends AsyncMatcher {
-  final Matcher? _matcher;
-
-  const Throws([Matcher? matcher]) : _matcher = matcher;
-
-  // Avoid async/await so we synchronously fail if we match a synchronous
-  // function.
-  @override
-  dynamic /*FutureOr<String>*/ matchAsync(item) {
-    if (item is! Function && item is! Future) {
-      return 'was not a Function or Future';
-    }
-
-    if (item is Future) {
-      return _matchFuture(item, 'emitted ');
-    }
-
-    try {
-      var value = item();
-      if (value is Future) {
-        return _matchFuture(value, 'returned a Future that emitted ');
-      }
-
-      return indent(prettyPrint(value), first: 'returned ');
-    } catch (error, trace) {
-      return _check(error, trace);
-    }
-  }
-
-  /// Matches [future], using try/catch since `onError` doesn't seem to work
-  /// properly in nnbd.
-  Future<String?> _matchFuture(
-      Future<dynamic> future, String messagePrefix) async {
-    try {
-      var value = await future;
-      return indent(prettyPrint(value), first: messagePrefix);
-    } catch (error, trace) {
-      return _check(error, trace);
-    }
-  }
-
-  @override
-  Description describe(Description description) {
-    if (_matcher == null) {
-      return description.add('throws');
-    } else {
-      return description.add('throws ').addDescriptionOf(_matcher);
-    }
-  }
-
-  /// Verifies that [error] matches [_matcher] and returns a [String]
-  /// description of the failure if it doesn't.
-  String? _check(error, StackTrace? trace) {
-    if (_matcher == null) return null;
-
-    var matchState = {};
-    if (_matcher!.matches(error, matchState)) return null;
-
-    var result = _matcher!
-        .describeMismatch(error, StringDescription(), matchState, false)
-        .toString();
-
-    var buffer = StringBuffer();
-    buffer.writeln(indent(prettyPrint(error), first: 'threw '));
-    if (trace != null) {
-      buffer.writeln(indent(
-          TestHandle.current.formatStackTrace(trace).toString(),
-          first: 'stack '));
-    }
-    if (result.isNotEmpty) buffer.writeln(indent(result, first: 'which '));
-    return buffer.toString().trimRight();
-  }
-}
diff --git a/pkgs/test_api/lib/src/expect/throws_matchers.dart b/pkgs/test_api/lib/src/expect/throws_matchers.dart
deleted file mode 100644
index edf777b..0000000
--- a/pkgs/test_api/lib/src/expect/throws_matchers.dart
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:matcher/matcher.dart';
-
-import 'throws_matcher.dart';
-
-/// A matcher for functions that throw ArgumentError.
-///
-/// See [throwsA] for objects that this can be matched against.
-const Matcher throwsArgumentError = Throws(isArgumentError);
-
-/// A matcher for functions that throw ConcurrentModificationError.
-///
-/// See [throwsA] for objects that this can be matched against.
-const Matcher throwsConcurrentModificationError =
-    Throws(isConcurrentModificationError);
-
-/// A matcher for functions that throw CyclicInitializationError.
-///
-/// See [throwsA] for objects that this can be matched against.
-@Deprecated('throwsCyclicInitializationError has been deprecated, because '
-    'the type will longer exists in Dart 3.0. It will now catch any kind of '
-    'error, not only CyclicInitializationError.')
-const Matcher throwsCyclicInitializationError = Throws(TypeMatcher<Error>());
-
-/// A matcher for functions that throw Exception.
-///
-/// See [throwsA] for objects that this can be matched against.
-const Matcher throwsException = Throws(isException);
-
-/// A matcher for functions that throw FormatException.
-///
-/// See [throwsA] for objects that this can be matched against.
-const Matcher throwsFormatException = Throws(isFormatException);
-
-/// A matcher for functions that throw NoSuchMethodError.
-///
-/// See [throwsA] for objects that this can be matched against.
-const Matcher throwsNoSuchMethodError = Throws(isNoSuchMethodError);
-
-/// A matcher for functions that throw NullThrownError.
-///
-/// See [throwsA] for objects that this can be matched against.
-@Deprecated('throwsNullThrownError has been deprecated, because '
-    'NullThrownError has been replaced with TypeError. '
-    'Use `throwsA(isA<TypeError>())` instead.')
-const Matcher throwsNullThrownError = Throws(TypeMatcher<TypeError>());
-
-/// A matcher for functions that throw RangeError.
-///
-/// See [throwsA] for objects that this can be matched against.
-const Matcher throwsRangeError = Throws(isRangeError);
-
-/// A matcher for functions that throw StateError.
-///
-/// See [throwsA] for objects that this can be matched against.
-const Matcher throwsStateError = Throws(isStateError);
-
-/// A matcher for functions that throw Exception.
-///
-/// See [throwsA] for objects that this can be matched against.
-const Matcher throwsUnimplementedError = Throws(isUnimplementedError);
-
-/// A matcher for functions that throw UnsupportedError.
-///
-/// See [throwsA] for objects that this can be matched against.
-const Matcher throwsUnsupportedError = Throws(isUnsupportedError);
diff --git a/pkgs/test_api/lib/src/expect/util/placeholder.dart b/pkgs/test_api/lib/src/expect/util/placeholder.dart
deleted file mode 100644
index ee2dc70..0000000
--- a/pkgs/test_api/lib/src/expect/util/placeholder.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// A class that's used as a default argument to detect whether an argument was
-/// passed.
-///
-/// We use a custom class for this rather than just `const Object()` so that
-/// callers can't accidentally pass the placeholder value.
-class _Placeholder {
-  const _Placeholder();
-}
-
-/// A placeholder to use as a default argument value to detect whether an
-/// argument was passed.
-const placeholder = _Placeholder();
diff --git a/pkgs/test_api/lib/src/expect/util/pretty_print.dart b/pkgs/test_api/lib/src/expect/util/pretty_print.dart
deleted file mode 100644
index f21399d..0000000
--- a/pkgs/test_api/lib/src/expect/util/pretty_print.dart
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:matcher/matcher.dart';
-import 'package:term_glyph/term_glyph.dart' as glyph;
-
-/// Indent each line in [string] by [first.length] spaces.
-///
-/// [first] is used in place of the first line's indentation.
-String indent(String text, {required String first}) {
-  final prefix = ' ' * first.length;
-  var lines = text.split('\n');
-  if (lines.length == 1) return '$first$text';
-
-  var buffer = StringBuffer('$first${lines.first}\n');
-
-  // Write out all but the first and last lines with [prefix].
-  for (var line in lines.skip(1).take(lines.length - 2)) {
-    buffer.writeln('$prefix$line');
-  }
-  buffer.write('$prefix${lines.last}');
-  return buffer.toString();
-}
-
-/// Returns a pretty-printed representation of [value].
-///
-/// The matcher package doesn't expose its pretty-print function directly, but
-/// we can use it through StringDescription.
-String prettyPrint(value) =>
-    StringDescription().addDescriptionOf(value).toString();
-
-/// Indents [text], and adds a bullet at the beginning.
-String addBullet(String text) => indent(text, first: '${glyph.bullet} ');
-
-/// Converts [strings] to a bulleted list.
-String bullet(Iterable<String> strings) => strings.map(addBullet).join('\n');
-
-/// Returns [name] if [number] is 1, or the plural of [name] otherwise.
-///
-/// By default, this just adds "s" to the end of [name] to get the plural. If
-/// [plural] is passed, that's used instead.
-String pluralize(String name, int number, {String? plural}) {
-  if (number == 1) return name;
-  if (plural != null) return plural;
-  return '${name}s';
-}
diff --git a/pkgs/test_api/lib/src/frontend/async_matcher.dart b/pkgs/test_api/lib/src/frontend/async_matcher.dart
deleted file mode 100644
index a6b800a..0000000
--- a/pkgs/test_api/lib/src/frontend/async_matcher.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@Deprecated('Moved to src/expect/async_matcher.dart')
-library test_api.src.frontend.async_matcher;
-
-// Temporary re-export to reduce churn in flutter_test.
-export '../expect/async_matcher.dart';
diff --git a/pkgs/test_api/lib/src/frontend/expect.dart b/pkgs/test_api/lib/src/frontend/expect.dart
deleted file mode 100644
index 4354058..0000000
--- a/pkgs/test_api/lib/src/frontend/expect.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@Deprecated('Moved to src/expect/expect.dart')
-library test_api.src.frontend.expect;
-
-// Temporary re-export to avoid churn in analyzer tests.
-export '../expect/expect.dart';
diff --git a/pkgs/test_api/lib/src/frontend/fake.dart b/pkgs/test_api/lib/src/frontend/fake.dart
index 0057400..e3e0ea6 100644
--- a/pkgs/test_api/lib/src/frontend/fake.dart
+++ b/pkgs/test_api/lib/src/frontend/fake.dart
@@ -44,7 +44,7 @@
 /// [Fake] should strictly _not_ be used in any production code, especially if
 /// used within the context of Dart for Web (dart2js, DDC) and Dart for Mobile
 /// (Flutter).
-abstract class Fake {
+abstract mixin class Fake {
   @override
   dynamic noSuchMethod(Invocation invocation) {
     throw UnimplementedError(invocation.memberName.toString().split('"')[1]);
diff --git a/pkgs/test_api/lib/src/scaffolding/spawn_hybrid.dart b/pkgs/test_api/lib/src/scaffolding/spawn_hybrid.dart
index 6e01fe8..2186894 100644
--- a/pkgs/test_api/lib/src/scaffolding/spawn_hybrid.dart
+++ b/pkgs/test_api/lib/src/scaffolding/spawn_hybrid.dart
@@ -32,7 +32,7 @@
       break;
 
     case 'error':
-      var error = RemoteException.deserialize(message['error']);
+      var error = RemoteException.deserialize(message['error'] as Map);
       sink.addError(error.error, error.stackTrace);
       break;
   }
@@ -89,7 +89,11 @@
 ///
 /// **Note**: If you use this API, be sure to add a dependency on the
 /// **`stream_channel` package, since you're using its API as well!
-StreamChannel spawnHybridUri(uri, {Object? message, bool stayAlive = false}) {
+StreamChannel spawnHybridUri(
+  Object uri, {
+  Object? message,
+  bool stayAlive = false,
+}) {
   if (uri is String) {
     // Ensure that it can be parsed as a uri.
     Uri.parse(uri);
diff --git a/pkgs/test_api/lib/src/scaffolding/test_structure.dart b/pkgs/test_api/lib/src/scaffolding/test_structure.dart
index ec8691d..97c6d79 100644
--- a/pkgs/test_api/lib/src/scaffolding/test_structure.dart
+++ b/pkgs/test_api/lib/src/scaffolding/test_structure.dart
@@ -70,11 +70,11 @@
 /// avoid this flag if possible and instead use the test runner flag `-n` to
 /// filter tests by name.
 @isTest
-void test(description, dynamic Function() body,
+void test(Object? description, dynamic Function() body,
     {String? testOn,
     Timeout? timeout,
-    skip,
-    tags,
+    Object? skip,
+    Object? tags,
     Map<String, dynamic>? onPlatform,
     int? retry,
     @Deprecated('Debug only') bool solo = false}) {
@@ -148,11 +148,11 @@
 /// avoid this flag if possible, and instead use the test runner flag `-n` to
 /// filter tests by name.
 @isTestGroup
-void group(description, dynamic Function() body,
+void group(Object? description, dynamic Function() body,
     {String? testOn,
     Timeout? timeout,
-    skip,
-    tags,
+    Object? skip,
+    Object? tags,
     Map<String, dynamic>? onPlatform,
     int? retry,
     @Deprecated('Debug only') bool solo = false}) {
diff --git a/pkgs/test_api/lib/test_api.dart b/pkgs/test_api/lib/test_api.dart
index 8e037cc..7804cda 100644
--- a/pkgs/test_api/lib/test_api.dart
+++ b/pkgs/test_api/lib/test_api.dart
@@ -6,12 +6,5 @@
     'Please use package:test.')
 library test_api;
 
-export 'expect.dart';
 export 'hooks.dart' show TestFailure;
 export 'scaffolding.dart';
-// Deprecated exports not surfaced through focused libraries.
-export 'src/expect/expect.dart' show ErrorFormatter;
-export 'src/expect/expect_async.dart' show expectAsync;
-export 'src/expect/throws_matcher.dart' show throws, Throws;
-// Not yet deprecated, but not exposed through focused libraries.
-export 'src/scaffolding/utils.dart' show registerException;
diff --git a/pkgs/test_api/pubspec.yaml b/pkgs/test_api/pubspec.yaml
index 51d5b23..c67c7ba 100644
--- a/pkgs/test_api/pubspec.yaml
+++ b/pkgs/test_api/pubspec.yaml
@@ -1,11 +1,11 @@
 name: test_api
-version: 0.4.18
+version: 0.6.1
 description: >-
   The user facing API for structuring Dart tests and checking expectations.
 repository: https://github.com/dart-lang/test/tree/master/pkgs/test_api
 
 environment:
-  sdk: ">=2.18.0 <3.0.0"
+  sdk: ^3.0.0
 
 dependencies:
   async: ^2.5.0
@@ -18,16 +18,12 @@
   string_scanner: ^1.1.0
   term_glyph: ^1.2.0
 
-  # Use a tight version constraint to ensure that a constraint on matcher
-  # properly constrains all features it provides.
-  matcher: '>=0.12.11 <0.12.15'
-
 dev_dependencies:
-  analyzer: '>=2.1.0 <6.0.0'
+  analyzer: '>=2.1.0 <7.0.0'
+  dart_flutter_team_lints: ^1.0.0
   fake_async: ^1.2.0
   glob: ^2.0.0
   graphs: ^2.0.0
   path: ^1.8.0
-  lints: '>=1.0.0 <3.0.0'
   test: any
   test_core: any
diff --git a/pkgs/test_api/test/backend/invoker_test.dart b/pkgs/test_api/test/backend/invoker_test.dart
index 490bb02..55e697b 100644
--- a/pkgs/test_api/test/backend/invoker_test.dart
+++ b/pkgs/test_api/test/backend/invoker_test.dart
@@ -184,10 +184,9 @@
           expect(lastState, equals(const State(Status.complete, Result.error)));
           expect(
               error,
-              equals(
-                  'This test failed after it had already completed. Make sure to '
-                  'use [expectAsync]\n'
-                  'or the [completes] matcher when testing async code.'));
+              equals('This test failed after it had already completed.\n'
+                  'Make sure to use a matching library which informs the '
+                  'test runner\nof pending async work.'));
         }
       ]);
 
@@ -316,10 +315,9 @@
         (error) {
           expect(
               error,
-              equals(
-                  'This test failed after it had already completed. Make sure to '
-                  'use [expectAsync]\n'
-                  'or the [completes] matcher when testing async code.'));
+              equals('This test failed after it had already completed.\n'
+                  'Make sure to use a matching library which informs the '
+                  'test runner\nof pending async work.'));
         }
       ]);
 
diff --git a/pkgs/test_api/test/backend/metadata_test.dart b/pkgs/test_api/test/backend/metadata_test.dart
index f900b13..c9a0f78 100644
--- a/pkgs/test_api/test/backend/metadata_test.dart
+++ b/pkgs/test_api/test/backend/metadata_test.dart
@@ -140,14 +140,16 @@
       });
 
       var key = metadata.onPlatform.keys.first;
-      expect(key.evaluate(SuitePlatform(Runtime.chrome)), isTrue);
-      expect(key.evaluate(SuitePlatform(Runtime.vm)), isFalse);
+      expect(
+          key.evaluate(SuitePlatform(Runtime.chrome, compiler: null)), isTrue);
+      expect(key.evaluate(SuitePlatform(Runtime.vm, compiler: null)), isFalse);
       var value = metadata.onPlatform.values.first;
       expect(value.timeout.scaleFactor, equals(2));
 
       key = metadata.onPlatform.keys.last;
-      expect(key.evaluate(SuitePlatform(Runtime.vm)), isTrue);
-      expect(key.evaluate(SuitePlatform(Runtime.chrome)), isFalse);
+      expect(key.evaluate(SuitePlatform(Runtime.vm, compiler: null)), isTrue);
+      expect(
+          key.evaluate(SuitePlatform(Runtime.chrome, compiler: null)), isFalse);
       value = metadata.onPlatform.values.last;
       expect(value.skip, isTrue);
       expect(value.timeout.scaleFactor, equals(3));
@@ -200,6 +202,10 @@
       Metadata.parse(testOn: 'vm || browser').validatePlatformSelectors({'vm'});
     });
 
+    test('succeeds if testOn uses valid compilers', () {
+      Metadata.parse(testOn: 'dart2js || kernel').validatePlatformSelectors({});
+    });
+
     test('fails if onPlatform uses an invalid platform', () {
       expect(() {
         Metadata.parse(onPlatform: {'unknown': Skip()})
@@ -212,6 +218,12 @@
         Metadata.parse(testOn: 'unknown').validatePlatformSelectors({'vm'});
       }, throwsFormatException);
     });
+
+    test('fails if testOn uses an invalid compiler', () {
+      expect(() {
+        Metadata.parse(testOn: 'foo2bar').validatePlatformSelectors({});
+      }, throwsFormatException);
+    });
   });
 
   group('change', () {
diff --git a/pkgs/test_api/test/frontend/expect_async_test.dart b/pkgs/test_api/test/frontend/expect_async_test.dart
deleted file mode 100644
index dde2e41..0000000
--- a/pkgs/test_api/test/frontend/expect_async_test.dart
+++ /dev/null
@@ -1,385 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:fake_async/fake_async.dart';
-import 'package:test/test.dart';
-import 'package:test_api/src/backend/live_test.dart';
-import 'package:test_api/src/backend/state.dart';
-
-import '../utils.dart';
-
-void main() {
-  group('supports a function with this many arguments:', () {
-    test('0', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync0(() {
-          callbackRun = true;
-        })();
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('1', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync1((int arg) {
-          expect(arg, equals(1));
-          callbackRun = true;
-        })(1);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('2', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync2((arg1, arg2) {
-          expect(arg1, equals(1));
-          expect(arg2, equals(2));
-          callbackRun = true;
-        })(1, 2);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('3', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync3((arg1, arg2, arg3) {
-          expect(arg1, equals(1));
-          expect(arg2, equals(2));
-          expect(arg3, equals(3));
-          callbackRun = true;
-        })(1, 2, 3);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('4', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync4((arg1, arg2, arg3, arg4) {
-          expect(arg1, equals(1));
-          expect(arg2, equals(2));
-          expect(arg3, equals(3));
-          expect(arg4, equals(4));
-          callbackRun = true;
-        })(1, 2, 3, 4);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('5', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync5((arg1, arg2, arg3, arg4, arg5) {
-          expect(arg1, equals(1));
-          expect(arg2, equals(2));
-          expect(arg3, equals(3));
-          expect(arg4, equals(4));
-          expect(arg5, equals(5));
-          callbackRun = true;
-        })(1, 2, 3, 4, 5);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('6', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync6((arg1, arg2, arg3, arg4, arg5, arg6) {
-          expect(arg1, equals(1));
-          expect(arg2, equals(2));
-          expect(arg3, equals(3));
-          expect(arg4, equals(4));
-          expect(arg5, equals(5));
-          expect(arg6, equals(6));
-          callbackRun = true;
-        })(1, 2, 3, 4, 5, 6);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-  });
-
-  group('with optional arguments', () {
-    test('allows them to be passed', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync1(([arg = 1]) {
-          expect(arg, equals(2));
-          callbackRun = true;
-        })(2);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('allows them not to be passed', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync1(([arg = 1]) {
-          expect(arg, equals(1));
-          callbackRun = true;
-        })();
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-  });
-
-  group('by default', () {
-    test("won't allow the test to complete until it's called", () {
-      return expectTestBlocks(
-          () => expectAsync0(() {}), (callback) => callback());
-    });
-
-    test('may only be called once', () async {
-      var liveTest = await runTestBody(() {
-        var callback = expectAsync0(() {});
-        callback();
-        callback();
-      });
-
-      expectTestFailed(
-          liveTest, 'Callback called more times than expected (1).');
-    });
-  });
-
-  group('with count', () {
-    test(
-        "won't allow the test to complete until it's called at least that "
-        'many times', () async {
-      late LiveTest liveTest;
-      late Future future;
-      liveTest = createTest(() {
-        var callback = expectAsync0(() {}, count: 3);
-
-        future = () async {
-          await pumpEventQueue();
-          expect(liveTest.state.status, equals(Status.running));
-          callback();
-
-          await pumpEventQueue();
-          expect(liveTest.state.status, equals(Status.running));
-          callback();
-
-          await pumpEventQueue();
-          expect(liveTest.state.status, equals(Status.running));
-          callback();
-        }();
-      });
-
-      await liveTest.run();
-      expectTestPassed(liveTest);
-      // Ensure that the outer test doesn't complete until the inner future
-      // completes.
-      await future;
-    });
-
-    test("will throw an error if it's called more than that many times",
-        () async {
-      var liveTest = await runTestBody(() {
-        var callback = expectAsync0(() {}, count: 3);
-        callback();
-        callback();
-        callback();
-        callback();
-      });
-
-      expectTestFailed(
-          liveTest, 'Callback called more times than expected (3).');
-    });
-
-    group('0,', () {
-      test("won't block the test's completion", () {
-        expectAsync0(() {}, count: 0);
-      });
-
-      test("will throw an error if it's ever called", () async {
-        var liveTest = await runTestBody(() {
-          expectAsync0(() {}, count: 0)();
-        });
-
-        expectTestFailed(
-            liveTest, 'Callback called more times than expected (0).');
-      });
-    });
-  });
-
-  group('with max', () {
-    test('will allow the callback to be called that many times', () {
-      var callback = expectAsync0(() {}, max: 3);
-      callback();
-      callback();
-      callback();
-    });
-
-    test('will allow the callback to be called fewer than that many times', () {
-      var callback = expectAsync0(() {}, max: 3);
-      callback();
-    });
-
-    test("will throw an error if it's called more than that many times",
-        () async {
-      var liveTest = await runTestBody(() {
-        var callback = expectAsync0(() {}, max: 3);
-        callback();
-        callback();
-        callback();
-        callback();
-      });
-
-      expectTestFailed(
-          liveTest, 'Callback called more times than expected (3).');
-    });
-
-    test('-1, will allow the callback to be called any number of times', () {
-      var callback = expectAsync0(() {}, max: -1);
-      for (var i = 0; i < 20; i++) {
-        callback();
-      }
-    });
-  });
-
-  test('will throw an error if max is less than count', () {
-    expect(() => expectAsync0(() {}, max: 1, count: 2), throwsArgumentError);
-  });
-
-  group('expectAsyncUntil()', () {
-    test("won't allow the test to complete until isDone returns true",
-        () async {
-      late LiveTest liveTest;
-      late Future future;
-      liveTest = createTest(() {
-        var done = false;
-        var callback = expectAsyncUntil0(() {}, () => done);
-
-        future = () async {
-          await pumpEventQueue();
-          expect(liveTest.state.status, equals(Status.running));
-          callback();
-          await pumpEventQueue();
-          expect(liveTest.state.status, equals(Status.running));
-          done = true;
-          callback();
-        }();
-      });
-
-      await liveTest.run();
-      expectTestPassed(liveTest);
-      // Ensure that the outer test doesn't complete until the inner future
-      // completes.
-      await future;
-    });
-
-    test("doesn't call isDone until after the callback is called", () {
-      var callbackRun = false;
-      expectAsyncUntil0(() => callbackRun = true, () {
-        expect(callbackRun, isTrue);
-        return true;
-      })();
-    });
-  });
-
-  test('allows errors', () async {
-    var liveTest = await runTestBody(() {
-      expect(expectAsync0(() => throw 'oh no'), throwsA('oh no'));
-    });
-
-    expectTestPassed(liveTest);
-  });
-
-  test('may be called in a non-test zone', () async {
-    var liveTest = await runTestBody(() {
-      var callback = expectAsync0(() {});
-      Zone.root.run(callback);
-    });
-    expectTestPassed(liveTest);
-  });
-
-  test('may be called in a FakeAsync zone that does not run further', () async {
-    var liveTest = await runTestBody(() {
-      FakeAsync().run((_) {
-        var callback = expectAsync0(() {});
-        callback();
-      });
-    });
-    expectTestPassed(liveTest);
-  });
-
-  group('old-style expectAsync()', () {
-    test('works with no arguments', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync(() {
-          callbackRun = true;
-        })();
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('works with dynamic arguments', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync((arg1, arg2) {
-          callbackRun = true;
-        })(1, 2);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('works with non-nullable arguments', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync((int arg1, int arg2) {
-          callbackRun = true;
-        })(1, 2);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test('works with 6 arguments', () async {
-      var callbackRun = false;
-      var liveTest = await runTestBody(() {
-        expectAsync((arg1, arg2, arg3, arg4, arg5, arg6) {
-          callbackRun = true;
-        })(1, 2, 3, 4, 5, 6);
-      });
-
-      expectTestPassed(liveTest);
-      expect(callbackRun, isTrue);
-    });
-
-    test("doesn't support a function with 7 arguments", () {
-      // ignore: no_leading_underscores_for_local_identifiers
-      expect(() => expectAsync((_a, _b, _c, _d, _e, _f, _g) {}),
-          throwsArgumentError);
-    });
-  });
-}
diff --git a/pkgs/test_api/test/frontend/expect_test.dart b/pkgs/test_api/test/frontend/expect_test.dart
deleted file mode 100644
index ee8d243..0000000
--- a/pkgs/test_api/test/frontend/expect_test.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test/test.dart';
-
-import '../utils.dart';
-
-void main() {
-  group('returned Future from expectLater()', () {
-    test('completes immediately for a sync matcher', () {
-      expect(expectLater(true, isTrue), completes);
-    });
-
-    test('contains the expect failure', () {
-      expect(expectLater(Future.value(true), completion(isFalse)),
-          throwsA(isTestFailure(anything)));
-    });
-
-    test('contains an async error', () {
-      expect(expectLater(Future.error('oh no'), completion(isFalse)),
-          throwsA('oh no'));
-    });
-  });
-
-  group('an async matcher that fails synchronously', () {
-    test('throws synchronously', () {
-      expect(() => expect(() {}, throws), throwsA(isTestFailure(anything)));
-    });
-
-    test('can be used with synchronous operators', () {
-      expect(() {}, isNot(throws));
-    });
-  });
-}
diff --git a/pkgs/test_api/test/frontend/matcher/completion_test.dart b/pkgs/test_api/test/frontend/matcher/completion_test.dart
deleted file mode 100644
index 1aee139..0000000
--- a/pkgs/test_api/test/frontend/matcher/completion_test.dart
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:test/test.dart';
-import 'package:test_api/src/backend/state.dart';
-
-import '../../utils.dart';
-
-void main() {
-  group('[doesNotComplete]', () {
-    test('fails when provided a non future', () async {
-      var liveTest = await runTestBody(() {
-        expect(10, doesNotComplete);
-      });
-
-      expectTestFailed(liveTest, contains('10 is not a Future'));
-    });
-
-    test('succeeds when a future does not complete', () {
-      var completer = Completer();
-      expect(completer.future, doesNotComplete);
-    });
-
-    test('fails when a future does complete', () async {
-      var liveTest = await runTestBody(() {
-        var completer = Completer();
-        completer.complete(null);
-        expect(completer.future, doesNotComplete);
-      });
-
-      expectTestFailed(
-          liveTest,
-          'Future was not expected to complete but completed with a value of'
-          ' null');
-    });
-
-    test('fails when a future completes after the expect', () async {
-      var liveTest = await runTestBody(() {
-        var completer = Completer();
-        expect(completer.future, doesNotComplete);
-        completer.complete(null);
-      });
-
-      expectTestFailed(
-          liveTest,
-          'Future was not expected to complete but completed with a value of'
-          ' null');
-    });
-
-    test('fails when a future eventually completes', () async {
-      var liveTest = await runTestBody(() {
-        var completer = Completer();
-        expect(completer.future, doesNotComplete);
-        Future(() async {
-          await pumpEventQueue(times: 10);
-        }).then(completer.complete);
-      });
-
-      expectTestFailed(
-          liveTest,
-          'Future was not expected to complete but completed with a value of'
-          ' null');
-    });
-  });
-  group('[completes]', () {
-    test('blocks the test until the Future completes', () {
-      return expectTestBlocks(() {
-        var completer = Completer();
-        expect(completer.future, completes);
-        return completer;
-      }, (completer) => completer.complete());
-    });
-
-    test('with an error', () async {
-      var liveTest = await runTestBody(() {
-        expect(Future.error('X'), completes);
-      });
-
-      expect(liveTest.state.status, equals(Status.complete));
-      expect(liveTest.state.result, equals(Result.error));
-      expect(liveTest.errors, hasLength(1));
-      expect(liveTest.errors.first.error, equals('X'));
-    });
-
-    test('with a failure', () async {
-      var liveTest = await runTestBody(() {
-        expect(Future.error(TestFailure('oh no')), completes);
-      });
-
-      expectTestFailed(liveTest, 'oh no');
-    });
-
-    test('with a non-future', () async {
-      var liveTest = await runTestBody(() {
-        expect(10, completes);
-      });
-
-      expectTestFailed(
-          liveTest,
-          'Expected: completes successfully\n'
-          '  Actual: <10>\n'
-          '   Which: was not a Future\n');
-    });
-
-    test('with a successful future', () {
-      expect(Future.value('1'), completes);
-    });
-  });
-
-  group('[completion]', () {
-    test('blocks the test until the Future completes', () {
-      return expectTestBlocks(() {
-        var completer = Completer();
-        expect(completer.future, completion(isNull));
-        return completer;
-      }, (completer) => completer.complete());
-    });
-
-    test('with an error', () async {
-      var liveTest = await runTestBody(() {
-        expect(Future.error('X'), completion(isNull));
-      });
-
-      expect(liveTest.state.status, equals(Status.complete));
-      expect(liveTest.state.result, equals(Result.error));
-      expect(liveTest.errors, hasLength(1));
-      expect(liveTest.errors.first.error, equals('X'));
-    });
-
-    test('with a failure', () async {
-      var liveTest = await runTestBody(() {
-        expect(Future.error(TestFailure('oh no')), completion(isNull));
-      });
-
-      expectTestFailed(liveTest, 'oh no');
-    });
-
-    test('with a non-future', () async {
-      var liveTest = await runTestBody(() {
-        expect(10, completion(equals(10)));
-      });
-
-      expectTestFailed(
-          liveTest,
-          'Expected: completes to a value that <10>\n'
-          '  Actual: <10>\n'
-          '   Which: was not a Future\n');
-    });
-
-    test('with an incorrect value', () async {
-      var liveTest = await runTestBody(() {
-        expect(Future.value('a'), completion(equals('b')));
-      });
-
-      expectTestFailed(
-          liveTest,
-          allOf([
-            startsWith("Expected: completes to a value that 'b'\n"
-                '  Actual: <'),
-            endsWith('>\n'
-                "   Which: emitted 'a'\n"
-                '            which is different.\n'
-                '                  Expected: b\n'
-                '                    Actual: a\n'
-                '                            ^\n'
-                '                   Differ at offset 0\n')
-          ]));
-    });
-
-    test("blocks expectLater's Future", () async {
-      var completer = Completer();
-      var fired = false;
-      unawaited(expectLater(completer.future, completion(equals(1))).then((_) {
-        fired = true;
-      }));
-
-      await pumpEventQueue();
-      expect(fired, isFalse);
-
-      completer.complete(1);
-      await pumpEventQueue();
-      expect(fired, isTrue);
-    });
-  });
-}
diff --git a/pkgs/test_api/test/frontend/matcher/prints_test.dart b/pkgs/test_api/test/frontend/matcher/prints_test.dart
deleted file mode 100644
index 92ab6a7..0000000
--- a/pkgs/test_api/test/frontend/matcher/prints_test.dart
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:test/test.dart';
-
-import '../../utils.dart';
-
-void main() {
-  group('synchronous', () {
-    test('passes with an expected print', () {
-      expect(() => print('Hello, world!'), prints('Hello, world!\n'));
-    });
-
-    test('combines multiple prints', () {
-      expect(() {
-        print('Hello');
-        print('World!');
-      }, prints('Hello\nWorld!\n'));
-    });
-
-    test('works with a Matcher', () {
-      expect(() => print('Hello, world!'), prints(contains('Hello')));
-    });
-
-    test('describes a failure nicely', () async {
-      void local() => print('Hello, world!');
-      var liveTest = await runTestBody(() {
-        expect(local, prints('Goodbye, world!\n'));
-      });
-
-      expectTestFailed(
-          liveTest,
-          allOf([
-            startsWith("Expected: prints 'Goodbye, world!\\n'\n"
-                "            ''\n"
-                '  Actual: <'),
-            endsWith('>\n'
-                "   Which: printed 'Hello, world!\\n'\n"
-                "                    ''\n"
-                '            which is different.\n'
-                '                  Expected: Goodbye, w ...\n'
-                '                    Actual: Hello, wor ...\n'
-                '                            ^\n'
-                '                   Differ at offset 0\n')
-          ]));
-    });
-
-    test('describes a failure with a non-descriptive Matcher nicely', () async {
-      void local() => print('Hello, world!');
-      var liveTest = await runTestBody(() {
-        expect(local, prints(contains('Goodbye')));
-      });
-
-      expectTestFailed(
-          liveTest,
-          allOf([
-            startsWith("Expected: prints contains 'Goodbye'\n"
-                '  Actual: <'),
-            endsWith('>\n'
-                "   Which: printed 'Hello, world!\\n'\n"
-                "                    ''\n")
-          ]));
-    });
-
-    test('describes a failure with no text nicely', () async {
-      void local() {}
-      var liveTest = await runTestBody(() {
-        expect(local, prints(contains('Goodbye')));
-      });
-
-      expectTestFailed(
-          liveTest,
-          allOf([
-            startsWith("Expected: prints contains 'Goodbye'\n"
-                '  Actual: <'),
-            endsWith('>\n'
-                '   Which: printed nothing\n')
-          ]));
-    });
-
-    test('with a non-function', () async {
-      var liveTest = await runTestBody(() {
-        expect(10, prints(contains('Goodbye')));
-      });
-
-      expectTestFailed(
-          liveTest,
-          "Expected: prints contains 'Goodbye'\n"
-          '  Actual: <10>\n'
-          '   Which: was not a unary Function\n');
-    });
-  });
-
-  group('asynchronous', () {
-    test('passes with an expected print', () {
-      expect(() => Future(() => print('Hello, world!')),
-          prints('Hello, world!\n'));
-    });
-
-    test('combines multiple prints', () {
-      expect(
-          () => Future(() {
-                print('Hello');
-                print('World!');
-              }),
-          prints('Hello\nWorld!\n'));
-    });
-
-    test('works with a Matcher', () {
-      expect(() => Future(() => print('Hello, world!')),
-          prints(contains('Hello')));
-    });
-
-    test('describes a failure nicely', () async {
-      void local() => Future(() => print('Hello, world!'));
-      var liveTest = await runTestBody(() {
-        expect(local, prints('Goodbye, world!\n'));
-      });
-
-      expectTestFailed(
-          liveTest,
-          allOf([
-            startsWith("Expected: prints 'Goodbye, world!\\n'\n"
-                "            ''\n"
-                '  Actual: <'),
-            contains('>\n'
-                "   Which: printed 'Hello, world!\\n'\n"
-                "                    ''\n"
-                '            which is different.\n'
-                '                  Expected: Goodbye, w ...\n'
-                '                    Actual: Hello, wor ...\n'
-                '                            ^\n'
-                '                   Differ at offset 0')
-          ]));
-    });
-
-    test('describes a failure with a non-descriptive Matcher nicely', () async {
-      void local() => Future(() => print('Hello, world!'));
-      var liveTest = await runTestBody(() {
-        expect(local, prints(contains('Goodbye')));
-      });
-
-      expectTestFailed(
-          liveTest,
-          allOf([
-            startsWith("Expected: prints contains 'Goodbye'\n"
-                '  Actual: <'),
-            contains('>\n'
-                "   Which: printed 'Hello, world!\\n'\n"
-                "                    ''")
-          ]));
-    });
-
-    test('describes a failure with no text nicely', () async {
-      void local() => Future.value();
-      var liveTest = await runTestBody(() {
-        expect(local, prints(contains('Goodbye')));
-      });
-
-      expectTestFailed(
-          liveTest,
-          allOf([
-            startsWith("Expected: prints contains 'Goodbye'\n"
-                '  Actual: <'),
-            contains('>\n'
-                '   Which: printed nothing')
-          ]));
-    });
-
-    test("won't let the test end until the Future completes", () {
-      return expectTestBlocks(() {
-        var completer = Completer();
-        expect(() => completer.future, prints(isEmpty));
-        return completer;
-      }, (completer) => completer.complete());
-    });
-
-    test("blocks expectLater's Future", () async {
-      var completer = Completer();
-      var fired = false;
-
-      unawaited(expectLater(() {
-        scheduleMicrotask(() => print('hello!'));
-        return completer.future;
-      }, prints('hello!\n'))
-          .then((_) {
-        fired = true;
-      }));
-
-      await pumpEventQueue();
-      expect(fired, isFalse);
-
-      completer.complete();
-      await pumpEventQueue();
-      expect(fired, isTrue);
-    });
-  });
-}
diff --git a/pkgs/test_api/test/frontend/matcher/throws_test.dart b/pkgs/test_api/test/frontend/matcher/throws_test.dart
deleted file mode 100644
index 40b2be6..0000000
--- a/pkgs/test_api/test/frontend/matcher/throws_test.dart
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:test/test.dart';
-
-import '../../utils.dart';
-
-void main() {
-  group('synchronous', () {
-    group('[throws]', () {
-      test('with a function that throws an error', () {
-        expect(() => throw 'oh no', throws);
-      });
-
-      test("with a function that doesn't throw", () async {
-        void local() {}
-        var liveTest = await runTestBody(() {
-          expect(local, throws);
-        });
-
-        expectTestFailed(
-            liveTest,
-            allOf([
-              startsWith('Expected: throws\n'
-                  '  Actual: <'),
-              endsWith('>\n'
-                  '   Which: returned <null>\n')
-            ]));
-      });
-
-      test('with a non-function', () async {
-        var liveTest = await runTestBody(() {
-          expect(10, throws);
-        });
-
-        expectTestFailed(
-            liveTest,
-            'Expected: throws\n'
-            '  Actual: <10>\n'
-            '   Which: was not a Function or Future\n');
-      });
-    });
-
-    group('[throwsA]', () {
-      test('with a function that throws an identical error', () {
-        expect(() => throw 'oh no', throwsA('oh no'));
-      });
-
-      test('with a function that throws a matching error', () {
-        expect(() => throw FormatException('bad'), throwsA(isFormatException));
-      });
-
-      test("with a function that doesn't throw", () async {
-        void local() {}
-        var liveTest = await runTestBody(() {
-          expect(local, throwsA('oh no'));
-        });
-
-        expectTestFailed(
-            liveTest,
-            allOf([
-              startsWith("Expected: throws 'oh no'\n"
-                  '  Actual: <'),
-              endsWith('>\n'
-                  '   Which: returned <null>\n')
-            ]));
-      });
-
-      test('with a non-function', () async {
-        var liveTest = await runTestBody(() {
-          expect(10, throwsA('oh no'));
-        });
-
-        expectTestFailed(
-            liveTest,
-            "Expected: throws 'oh no'\n"
-            '  Actual: <10>\n'
-            '   Which: was not a Function or Future\n');
-      });
-
-      test('with a function that throws the wrong error', () async {
-        var liveTest = await runTestBody(() {
-          expect(() => throw 'aw dang', throwsA('oh no'));
-        });
-
-        expectTestFailed(
-            liveTest,
-            allOf([
-              startsWith("Expected: throws 'oh no'\n"
-                  '  Actual: <'),
-              contains('>\n'
-                  "   Which: threw 'aw dang'\n"
-                  '          stack'),
-              endsWith('          which is different.\n'
-                  '                Expected: oh no\n'
-                  '                  Actual: aw dang\n'
-                  '                          ^\n'
-                  '                 Differ at offset 0\n')
-            ]));
-      });
-    });
-  });
-
-  group('asynchronous', () {
-    group('[throws]', () {
-      test('with a Future that throws an error', () {
-        expect(Future.error('oh no'), throws);
-      });
-
-      test("with a Future that doesn't throw", () async {
-        var liveTest = await runTestBody(() {
-          expect(Future.value(), throws);
-        });
-
-        expectTestFailed(
-            liveTest,
-            allOf([
-              startsWith('Expected: throws\n'
-                  '  Actual: <'),
-              endsWith('>\n'
-                  '   Which: emitted <null>\n')
-            ]));
-      });
-
-      test('with a closure that returns a Future that throws an error', () {
-        expect(() => Future.error('oh no'), throws);
-      });
-
-      test("with a closure that returns a Future that doesn't throw", () async {
-        var liveTest = await runTestBody(() {
-          expect(() => Future.value(), throws);
-        });
-
-        expectTestFailed(
-            liveTest,
-            allOf([
-              startsWith('Expected: throws\n'
-                  '  Actual: <'),
-              endsWith('>\n'
-                  '   Which: returned a Future that emitted <null>\n')
-            ]));
-      });
-
-      test("won't let the test end until the Future completes", () {
-        return expectTestBlocks(() {
-          var completer = Completer();
-          expect(completer.future, throws);
-          return completer;
-        }, (completer) => completer.completeError('oh no'));
-      });
-    });
-
-    group('[throwsA]', () {
-      test('with a Future that throws an identical error', () {
-        expect(Future.error('oh no'), throwsA('oh no'));
-      });
-
-      test('with a Future that throws a matching error', () {
-        expect(
-            Future.error(FormatException('bad')), throwsA(isFormatException));
-      });
-
-      test("with a Future that doesn't throw", () async {
-        var liveTest = await runTestBody(() {
-          expect(Future.value(), throwsA('oh no'));
-        });
-
-        expectTestFailed(
-            liveTest,
-            allOf([
-              startsWith("Expected: throws 'oh no'\n"
-                  '  Actual: <'),
-              endsWith('>\n'
-                  '   Which: emitted <null>\n')
-            ]));
-      });
-
-      test('with a Future that throws the wrong error', () async {
-        var liveTest = await runTestBody(() {
-          expect(Future.error('aw dang'), throwsA('oh no'));
-        });
-
-        expectTestFailed(
-            liveTest,
-            allOf([
-              startsWith("Expected: throws 'oh no'\n"
-                  '  Actual: <'),
-              contains('>\n'
-                  "   Which: threw 'aw dang'\n")
-            ]));
-      });
-
-      test('with a closure that returns a Future that throws a matching error',
-          () {
-        expect(() => Future.error(FormatException('bad')),
-            throwsA(isFormatException));
-      });
-
-      test("with a closure that returns a Future that doesn't throw", () async {
-        var liveTest = await runTestBody(() {
-          expect(() => Future.value(), throwsA('oh no'));
-        });
-
-        expectTestFailed(
-            liveTest,
-            allOf([
-              startsWith("Expected: throws 'oh no'\n"
-                  '  Actual: <'),
-              endsWith('>\n'
-                  '   Which: returned a Future that emitted <null>\n')
-            ]));
-      });
-
-      test('with closure that returns a Future that throws the wrong error',
-          () async {
-        var liveTest = await runTestBody(() {
-          expect(() => Future.error('aw dang'), throwsA('oh no'));
-        });
-
-        expectTestFailed(
-            liveTest,
-            allOf([
-              startsWith("Expected: throws 'oh no'\n"
-                  '  Actual: <'),
-              contains('>\n'
-                  "   Which: threw 'aw dang'\n")
-            ]));
-      });
-
-      test("won't let the test end until the Future completes", () {
-        return expectTestBlocks(() {
-          var completer = Completer();
-          expect(completer.future, throwsA('oh no'));
-          return completer;
-        }, (completer) => completer.completeError('oh no'));
-      });
-
-      test("blocks expectLater's Future", () async {
-        var completer = Completer();
-        var fired = false;
-        unawaited(expectLater(completer.future, throwsArgumentError).then((_) {
-          fired = true;
-        }));
-
-        await pumpEventQueue();
-        expect(fired, isFalse);
-
-        completer.completeError(ArgumentError('oh no'));
-        await pumpEventQueue();
-        expect(fired, isTrue);
-      });
-    });
-  });
-}
diff --git a/pkgs/test_api/test/frontend/matcher/throws_type_test.dart b/pkgs/test_api/test/frontend/matcher/throws_type_test.dart
deleted file mode 100644
index 6e0a482..0000000
--- a/pkgs/test_api/test/frontend/matcher/throws_type_test.dart
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test/test.dart';
-
-import '../../utils.dart';
-
-void main() {
-  group('[throwsArgumentError]', () {
-    test('passes when a ArgumentError is thrown', () {
-      expect(() => throw ArgumentError(''), throwsArgumentError);
-    });
-
-    test('fails when a non-ArgumentError is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw Exception(), throwsArgumentError);
-      });
-
-      expectTestFailed(liveTest,
-          startsWith("Expected: throws <Instance of 'ArgumentError'>"));
-    });
-  });
-
-  group('[throwsConcurrentModificationError]', () {
-    test('passes when a ConcurrentModificationError is thrown', () {
-      expect(() => throw ConcurrentModificationError(''),
-          throwsConcurrentModificationError);
-    });
-
-    test('fails when a non-ConcurrentModificationError is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw Exception(), throwsConcurrentModificationError);
-      });
-
-      expectTestFailed(
-          liveTest,
-          startsWith(
-              "Expected: throws <Instance of 'ConcurrentModificationError'>"));
-    });
-  });
-
-  group('[throwsCyclicInitializationError]', () {
-    test('passes when a CyclicInitializationError is thrown', () {
-      expect(
-          () => _CyclicInitializationFailure().x,
-          // ignore: deprecated_member_use
-          throwsCyclicInitializationError);
-    });
-
-    test('fails when a non-CyclicInitializationError is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw Exception(), throwsCyclicInitializationError);
-      });
-
-      expectTestFailed(
-          liveTest, startsWith("Expected: throws <Instance of 'Error'>"));
-    });
-  });
-
-  group('[throwsException]', () {
-    test('passes when a Exception is thrown', () {
-      expect(() => throw Exception(''), throwsException);
-    });
-
-    test('fails when a non-Exception is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw 'oh no', throwsException);
-      });
-
-      expectTestFailed(
-          liveTest, startsWith("Expected: throws <Instance of 'Exception'>"));
-    });
-  });
-
-  group('[throwsFormatException]', () {
-    test('passes when a FormatException is thrown', () {
-      expect(() => throw FormatException(''), throwsFormatException);
-    });
-
-    test('fails when a non-FormatException is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw Exception(), throwsFormatException);
-      });
-
-      expectTestFailed(liveTest,
-          startsWith("Expected: throws <Instance of 'FormatException'>"));
-    });
-  });
-
-  group('[throwsNoSuchMethodError]', () {
-    test('passes when a NoSuchMethodError is thrown', () {
-      expect(() {
-        (1 as dynamic).notAMethodOnInt();
-      }, throwsNoSuchMethodError);
-    });
-
-    test('fails when a non-NoSuchMethodError is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw Exception(), throwsNoSuchMethodError);
-      });
-
-      expectTestFailed(liveTest,
-          startsWith("Expected: throws <Instance of 'NoSuchMethodError'>"));
-    });
-  });
-
-  group('[throwsRangeError]', () {
-    test('passes when a RangeError is thrown', () {
-      expect(() => throw RangeError(''), throwsRangeError);
-    });
-
-    test('fails when a non-RangeError is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw Exception(), throwsRangeError);
-      });
-
-      expectTestFailed(
-          liveTest, startsWith("Expected: throws <Instance of 'RangeError'>"));
-    });
-  });
-
-  group('[throwsStateError]', () {
-    test('passes when a StateError is thrown', () {
-      expect(() => throw StateError(''), throwsStateError);
-    });
-
-    test('fails when a non-StateError is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw Exception(), throwsStateError);
-      });
-
-      expectTestFailed(
-          liveTest, startsWith("Expected: throws <Instance of 'StateError'>"));
-    });
-  });
-
-  group('[throwsUnimplementedError]', () {
-    test('passes when a UnimplementedError is thrown', () {
-      expect(() => throw UnimplementedError(''), throwsUnimplementedError);
-    });
-
-    test('fails when a non-UnimplementedError is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw Exception(), throwsUnimplementedError);
-      });
-
-      expectTestFailed(liveTest,
-          startsWith("Expected: throws <Instance of 'UnimplementedError'>"));
-    });
-  });
-
-  group('[throwsUnsupportedError]', () {
-    test('passes when a UnsupportedError is thrown', () {
-      expect(() => throw UnsupportedError(''), throwsUnsupportedError);
-    });
-
-    test('fails when a non-UnsupportedError is thrown', () async {
-      var liveTest = await runTestBody(() {
-        expect(() => throw Exception(), throwsUnsupportedError);
-      });
-
-      expectTestFailed(liveTest,
-          startsWith("Expected: throws <Instance of 'UnsupportedError'>"));
-    });
-  });
-}
-
-class _CyclicInitializationFailure {
-  late int x = y;
-  late int y = x;
-}
diff --git a/pkgs/test_api/test/frontend/never_called_test.dart b/pkgs/test_api/test/frontend/never_called_test.dart
deleted file mode 100644
index e9170f9..0000000
--- a/pkgs/test_api/test/frontend/never_called_test.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:term_glyph/term_glyph.dart' as glyph;
-import 'package:test/test.dart';
-
-import '../utils.dart';
-
-void main() {
-  setUpAll(() {
-    glyph.ascii = true;
-  });
-
-  test("doesn't throw if it isn't called", () async {
-    var liveTest = await runTestBody(() {
-      const Stream.empty().listen(neverCalled);
-    });
-
-    expectTestPassed(liveTest);
-  });
-
-  group("if it's called", () {
-    test('throws', () async {
-      var liveTest = await runTestBody(() {
-        neverCalled();
-      });
-
-      expectTestFailed(
-          liveTest,
-          'Callback should never have been called, but it was called with no '
-          'arguments.');
-    });
-
-    test('pretty-prints arguments', () async {
-      var liveTest = await runTestBody(() {
-        neverCalled(1, 'foo\nbar');
-      });
-
-      expectTestFailed(
-          liveTest,
-          'Callback should never have been called, but it was called with:\n'
-          '* <1>\n'
-          "* 'foo\\n'\n"
-          "    'bar'");
-    });
-
-    test('keeps the test alive', () async {
-      var liveTest = await runTestBody(() {
-        pumpEventQueue(times: 10).then(neverCalled);
-      });
-
-      expectTestFailed(
-          liveTest,
-          'Callback should never have been called, but it was called with:\n'
-          '* <null>');
-    });
-
-    test("can't be caught", () async {
-      var liveTest = await runTestBody(() {
-        try {
-          neverCalled();
-        } catch (_) {
-          // Do nothing.
-        }
-      });
-
-      expectTestFailed(
-          liveTest,
-          'Callback should never have been called, but it was called with '
-          'no arguments.');
-    });
-  });
-}
diff --git a/pkgs/test_api/test/frontend/stream_matcher_test.dart b/pkgs/test_api/test/frontend/stream_matcher_test.dart
deleted file mode 100644
index deb21fb..0000000
--- a/pkgs/test_api/test/frontend/stream_matcher_test.dart
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:async/async.dart';
-import 'package:term_glyph/term_glyph.dart' as glyph;
-import 'package:test/test.dart';
-
-import '../utils.dart';
-
-void main() {
-  setUpAll(() {
-    glyph.ascii = true;
-  });
-
-  late Stream stream;
-  late StreamQueue queue;
-  late Stream errorStream;
-  late StreamQueue errorQueue;
-  setUp(() {
-    stream = Stream.fromIterable([1, 2, 3, 4, 5]);
-    queue = StreamQueue(Stream.fromIterable([1, 2, 3, 4, 5]));
-    errorStream = Stream.fromFuture(Future.error('oh no!', StackTrace.current));
-    errorQueue = StreamQueue(
-        Stream.fromFuture(Future.error('oh no!', StackTrace.current)));
-  });
-
-  group('emits()', () {
-    test('matches the first event of a Stream', () {
-      expect(stream, emits(1));
-    });
-
-    test('rejects the first event of a Stream', () {
-      expect(
-          expectLater(stream, emits(2)),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should emit an event that <2>\n'),
-            endsWith('   Which: emitted * 1\n'
-                '                  * 2\n'
-                '                  * 3\n'
-                '                  * 4\n'
-                '                  * 5\n'
-                '                  x Stream closed.\n')
-          ])));
-    });
-
-    test('matches and consumes the next event of a StreamQueue', () {
-      expect(queue, emits(1));
-      expect(queue.next, completion(equals(2)));
-      expect(queue, emits(3));
-      expect(queue.next, completion(equals(4)));
-    });
-
-    test('rejects and does not consume the first event of a StreamQueue', () {
-      expect(
-          expectLater(queue, emits(2)),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should emit an event that <2>\n'),
-            endsWith('   Which: emitted * 1\n'
-                '                  * 2\n'
-                '                  * 3\n'
-                '                  * 4\n'
-                '                  * 5\n'
-                '                  x Stream closed.\n')
-          ])));
-
-      expect(queue, emits(1));
-    });
-
-    test('rejects an empty stream', () {
-      expect(
-          expectLater(Stream.empty(), emits(1)),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should emit an event that <1>\n'),
-            endsWith('   Which: emitted x Stream closed.\n')
-          ])));
-    });
-
-    test('forwards a stream error', () {
-      expect(expectLater(errorStream, emits(1)), throwsA('oh no!'));
-    });
-
-    test('wraps a normal matcher', () {
-      expect(queue, emits(lessThan(5)));
-      expect(expectLater(queue, emits(greaterThan(5))),
-          throwsTestFailure(anything));
-    });
-
-    test('returns a StreamMatcher as-is', () {
-      expect(queue, emits(emitsThrough(4)));
-      expect(queue, emits(5));
-    });
-  });
-
-  group('emitsDone', () {
-    test('succeeds for an empty stream', () {
-      expect(Stream.empty(), emitsDone);
-    });
-
-    test('fails for a stream with events', () {
-      expect(
-          expectLater(stream, emitsDone),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should be done\n'),
-            endsWith('   Which: emitted * 1\n'
-                '                  * 2\n'
-                '                  * 3\n'
-                '                  * 4\n'
-                '                  * 5\n'
-                '                  x Stream closed.\n')
-          ])));
-    });
-  });
-
-  group('emitsError()', () {
-    test('consumes a matching error', () {
-      expect(errorQueue, emitsError('oh no!'));
-      expect(errorQueue.hasNext, completion(isFalse));
-    });
-
-    test('fails for a non-matching error', () {
-      expect(
-          expectLater(errorStream, emitsError('oh heck')),
-          throwsTestFailure(allOf([
-            startsWith("Expected: should emit an error that 'oh heck'\n"),
-            contains('   Which: emitted ! oh no!\n'),
-            contains('                  x Stream closed.\n'
-                "            which threw 'oh no!'\n"
-                '                  stack '),
-            endsWith('                  which is different.\n'
-                '                        Expected: oh heck\n'
-                '                          Actual: oh no!\n'
-                '                                     ^\n'
-                '                         Differ at offset 3\n')
-          ])));
-    });
-
-    test('fails for a stream with events', () {
-      expect(
-          expectLater(stream, emitsDone),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should be done\n'),
-            endsWith('   Which: emitted * 1\n'
-                '                  * 2\n'
-                '                  * 3\n'
-                '                  * 4\n'
-                '                  * 5\n'
-                '                  x Stream closed.\n')
-          ])));
-    });
-  });
-
-  group('mayEmit()', () {
-    test('consumes a matching event', () {
-      expect(queue, mayEmit(1));
-      expect(queue, emits(2));
-    });
-
-    test('allows a non-matching event', () {
-      expect(queue, mayEmit('fish'));
-      expect(queue, emits(1));
-    });
-  });
-
-  group('emitsAnyOf()', () {
-    test('consumes an event that matches a matcher', () {
-      expect(queue, emitsAnyOf([2, 1, 3]));
-      expect(queue, emits(2));
-    });
-
-    test('consumes as many events as possible', () {
-      expect(
-          queue,
-          emitsAnyOf([
-            1,
-            emitsInOrder([1, 2]),
-            emitsInOrder([1, 2, 3])
-          ]));
-
-      expect(queue, emits(4));
-    });
-
-    test('fails if no matchers match', () {
-      expect(
-          expectLater(stream, emitsAnyOf([2, 3, 4])),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should do one of the following:\n'
-                '          * emit an event that <2>\n'
-                '          * emit an event that <3>\n'
-                '          * emit an event that <4>\n'),
-            endsWith('   Which: emitted * 1\n'
-                '                  * 2\n'
-                '                  * 3\n'
-                '                  * 4\n'
-                '                  * 5\n'
-                '                  x Stream closed.\n'
-                '            which failed all options:\n'
-                '                  * failed to emit an event that <2>\n'
-                '                  * failed to emit an event that <3>\n'
-                '                  * failed to emit an event that <4>\n')
-          ])));
-    });
-
-    test('allows an error if any matcher matches', () {
-      expect(errorStream, emitsAnyOf([1, 2, emitsError('oh no!')]));
-    });
-
-    test('rethrows an error if no matcher matches', () {
-      expect(
-          expectLater(errorStream, emitsAnyOf([1, 2, 3])), throwsA('oh no!'));
-    });
-  });
-
-  group('emitsInOrder()', () {
-    test('consumes matching events', () {
-      expect(queue, emitsInOrder([1, 2, emitsThrough(4)]));
-      expect(queue, emits(5));
-    });
-
-    test("fails if the matchers don't match in order", () {
-      expect(
-          expectLater(queue, emitsInOrder([1, 3, 2])),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should do the following in order:\n'
-                '          * emit an event that <1>\n'
-                '          * emit an event that <3>\n'
-                '          * emit an event that <2>\n'),
-            endsWith('   Which: emitted * 1\n'
-                '                  * 2\n'
-                '                  * 3\n'
-                '                  * 4\n'
-                '                  * 5\n'
-                '                  x Stream closed.\n'
-                "            which didn't emit an event that <3>\n")
-          ])));
-    });
-  });
-
-  group('emitsThrough()', () {
-    test('consumes events including those matching the matcher', () {
-      expect(queue, emitsThrough(emitsInOrder([3, 4])));
-      expect(queue, emits(5));
-    });
-
-    test('consumes the entire queue with emitsDone', () {
-      expect(queue, emitsThrough(emitsDone));
-      expect(queue.hasNext, completion(isFalse));
-    });
-
-    test('fails if the queue never matches the matcher', () {
-      expect(
-          expectLater(queue, emitsThrough(6)),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should eventually emit an event that <6>\n'),
-            endsWith('   Which: emitted * 1\n'
-                '                  * 2\n'
-                '                  * 3\n'
-                '                  * 4\n'
-                '                  * 5\n'
-                '                  x Stream closed.\n'
-                '            which never did emit an event that <6>\n')
-          ])));
-    });
-  });
-
-  group('mayEmitMultiple()', () {
-    test('consumes multiple instances of the given matcher', () {
-      expect(queue, mayEmitMultiple(lessThan(3)));
-      expect(queue, emits(3));
-    });
-
-    test('consumes zero instances of the given matcher', () {
-      expect(queue, mayEmitMultiple(6));
-      expect(queue, emits(1));
-    });
-
-    test("doesn't rethrow errors", () {
-      expect(errorQueue, mayEmitMultiple(1));
-      expect(errorQueue, emitsError('oh no!'));
-    });
-  });
-
-  group('neverEmits()', () {
-    test('succeeds if the event never matches', () {
-      expect(queue, neverEmits(6));
-      expect(queue, emits(1));
-    });
-
-    test('fails if the event matches', () {
-      expect(
-          expectLater(stream, neverEmits(4)),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should never emit an event that <4>\n'),
-            endsWith('   Which: emitted * 1\n'
-                '                  * 2\n'
-                '                  * 3\n'
-                '                  * 4\n'
-                '                  * 5\n'
-                '                  x Stream closed.\n'
-                '            which after 3 events did emit an event that <4>\n')
-          ])));
-    });
-
-    test('fails if emitsDone matches', () {
-      expect(expectLater(stream, neverEmits(emitsDone)),
-          throwsTestFailure(anything));
-    });
-
-    test("doesn't rethrow errors", () {
-      expect(errorQueue, neverEmits(6));
-      expect(errorQueue, emitsError('oh no!'));
-    });
-  });
-
-  group('emitsInAnyOrder()', () {
-    test('consumes events that match in any order', () {
-      expect(queue, emitsInAnyOrder([3, 1, 2]));
-      expect(queue, emits(4));
-    });
-
-    test("fails if the events don't match in any order", () {
-      expect(
-          expectLater(stream, emitsInAnyOrder([4, 1, 2])),
-          throwsTestFailure(allOf([
-            startsWith('Expected: should do the following in any order:\n'
-                '          * emit an event that <4>\n'
-                '          * emit an event that <1>\n'
-                '          * emit an event that <2>\n'),
-            endsWith('   Which: emitted * 1\n'
-                '                  * 2\n'
-                '                  * 3\n'
-                '                  * 4\n'
-                '                  * 5\n'
-                '                  x Stream closed.\n')
-          ])));
-    });
-
-    test("doesn't rethrow if some ordering matches", () {
-      expect(errorQueue, emitsInAnyOrder([emitsDone, emitsError('oh no!')]));
-    });
-
-    test('rethrows if no ordering matches', () {
-      expect(
-          expectLater(errorQueue, emitsInAnyOrder([1, emitsError('oh no!')])),
-          throwsA('oh no!'));
-    });
-  });
-
-  test('A custom StreamController doesn\'t hang on close', () async {
-    var controller = StreamController<void>();
-    var done = expectLater(controller.stream, emits(null));
-    controller.add(null);
-    await done;
-    await controller.close();
-  });
-}
diff --git a/pkgs/test_api/test/import_restrictions_test.dart b/pkgs/test_api/test/import_restrictions_test.dart
index f07c4c6..d155145 100644
--- a/pkgs/test_api/test/import_restrictions_test.dart
+++ b/pkgs/test_api/test/import_restrictions_test.dart
@@ -26,8 +26,8 @@
     test('must not import from other subdirectories', () async {
       final entryPoints = [
         _testApiLibrary('backend.dart'),
-        ...(await _ImportCheck.findEntrypointsUnder(
-            _testApiLibrary('src/backend')))
+        ...await _ImportCheck.findEntrypointsUnder(
+            _testApiLibrary('src/backend'))
       ];
       await for (final source
           in importCheck.transitiveSamePackageSources(entryPoints)) {
@@ -38,39 +38,6 @@
       }
     });
   });
-
-  group('expect', () {
-    test('must not be imported from any other library', () async {
-      final entryPoints = [
-        _testApiLibrary('hooks.dart'),
-        _testApiLibrary('scaffolding.dart'),
-        _testApiLibrary('fake.dart')
-      ];
-      await for (final source
-          in importCheck.transitiveSamePackageSources(entryPoints)) {
-        for (final import in source.imports) {
-          expect(import.path, isNot(contains('test_api.dart')),
-              reason: 'Invalid import from ${source.uri} : $import.');
-          expect(import.path, isNot(contains('expect')),
-              reason: 'Invalid import from ${source.uri} : $import.');
-        }
-      }
-    });
-
-    test('may only import hooks', () async {
-      final entryPoint = _testApiLibrary('expect.dart');
-      await for (final source
-          in importCheck.transitiveSamePackageSources([entryPoint])) {
-        // Transitive imports through `hooks.dart` don't follow this restriction
-        if (!source.uri.path.contains('expect')) continue;
-        for (final import in source.imports) {
-          expect(import.path,
-              anyOf(['test_api/hooks.dart', startsWith('test_api/src/expect')]),
-              reason: 'Invalid import from ${source.uri} : $import');
-        }
-      }
-    });
-  });
 }
 
 Uri _testApiLibrary(String path) => Uri.parse('package:test_api/$path');
diff --git a/pkgs/test_api/test/utils.dart b/pkgs/test_api/test/utils.dart
index 65dd5c5..c1fb2e3 100644
--- a/pkgs/test_api/test/utils.dart
+++ b/pkgs/test_api/test/utils.dart
@@ -6,14 +6,10 @@
 
 import 'package:test/test.dart';
 import 'package:test_api/src/backend/declarer.dart';
-import 'package:test_api/src/backend/group.dart';
 import 'package:test_api/src/backend/group_entry.dart';
-import 'package:test_api/src/backend/invoker.dart';
 import 'package:test_api/src/backend/live_test.dart';
-import 'package:test_api/src/backend/metadata.dart';
 import 'package:test_api/src/backend/runtime.dart';
 import 'package:test_api/src/backend/state.dart';
-import 'package:test_api/src/backend/suite.dart';
 import 'package:test_api/src/backend/suite_platform.dart';
 import 'package:test_core/src/runner/engine.dart';
 import 'package:test_core/src/runner/plugin/environment.dart';
@@ -21,7 +17,8 @@
 import 'package:test_core/src/runner/suite.dart';
 
 /// A dummy suite platform to use for testing suites.
-final suitePlatform = SuitePlatform(Runtime.vm);
+final suitePlatform =
+    SuitePlatform(Runtime.vm, compiler: Runtime.vm.defaultCompiler);
 
 // The last state change detected via [expectStates].
 State? lastState;
@@ -76,34 +73,12 @@
   ]);
 }
 
-/// Returns a matcher that matches a callback or Future that throws a
-/// [TestFailure] with the given [message].
-///
-/// [message] can be a string or a [Matcher].
-Matcher throwsTestFailure(message) => throwsA(isTestFailure(message));
-
 /// Returns a matcher that matches a [TestFailure] with the given [message].
 ///
 /// [message] can be a string or a [Matcher].
-Matcher isTestFailure(message) => const TypeMatcher<TestFailure>()
+Matcher isTestFailure(Object message) => const TypeMatcher<TestFailure>()
     .having((e) => e.message, 'message', message);
 
-/// Returns a local [LiveTest] that runs [body].
-LiveTest createTest(dynamic Function() body) {
-  var test = LocalTest('test', Metadata(chainStackTraces: true), body);
-  var suite = Suite(Group.root([test]), suitePlatform, ignoreTimeouts: false);
-  return test.load(suite);
-}
-
-/// Runs [body] as a test.
-///
-/// Once it completes, returns the [LiveTest] used to run it.
-Future<LiveTest> runTestBody(dynamic Function() body) async {
-  var liveTest = createTest(body);
-  await liveTest.run();
-  return liveTest;
-}
-
 /// Asserts that [liveTest] has completed and passed.
 ///
 /// If the test had any errors, they're surfaced nicely into the outer test.
@@ -123,36 +98,13 @@
 
 /// Asserts that [liveTest] failed with a single [TestFailure] whose message
 /// matches [message].
-void expectTestFailed(LiveTest liveTest, message) {
+void expectTestFailed(LiveTest liveTest, Object message) {
   expect(liveTest.state.status, equals(Status.complete));
   expect(liveTest.state.result, equals(Result.failure));
   expect(liveTest.errors, hasLength(1));
   expect(liveTest.errors.first.error, isTestFailure(message));
 }
 
-/// Assert that the [test] callback causes a test to block until [stopBlocking]
-/// is called at some later time.
-///
-/// [stopBlocking] is passed the return value of [test].
-Future expectTestBlocks(
-    dynamic Function() test, dynamic Function(dynamic) stopBlocking) async {
-  late LiveTest liveTest;
-  late Future future;
-  liveTest = createTest(() {
-    var value = test();
-    future = pumpEventQueue().then((_) {
-      expect(liveTest.state.status, equals(Status.running));
-      stopBlocking(value);
-    });
-  });
-
-  await liveTest.run();
-  expectTestPassed(liveTest);
-  // Ensure that the outer test doesn't complete until the inner future
-  // completes.
-  return future;
-}
-
 /// Runs [body] with a declarer, runs all the declared tests, and asserts that
 /// they pass.
 ///
diff --git a/pkgs/test_core/CHANGELOG.md b/pkgs/test_core/CHANGELOG.md
index 3cfc241..2a0b55f 100644
--- a/pkgs/test_core/CHANGELOG.md
+++ b/pkgs/test_core/CHANGELOG.md
@@ -1,15 +1,86 @@
-# 0.4.23-dev
+## 0.5.7-wip
+
+## 0.5.6
+
+* Add support for discontinuing after the first failing test with `--fail-fast`.
+
+## 0.5.5
+
+* Change "compiling <path>" to "loading <path>" message in all cases. Surface
+  the "loading" messages in the situations where previously only "compiling"
+  message would be used.
+
+## 0.5.4
+
+* Drop support for null unsafe Dart, bump SDK constraint to `3.0.0`.
+* Add `final` modifier on some implementation classes: `Configuration`,
+  `CustomRuntime`,`RuntimeSettings`, `SuiteConfiguration`.
+* Fix the `root_` fields in the JSON reporter when running a test on Windows
+  with an absolute path.
+* Allow the latest analyzer (6.x.x).
+
+## 0.5.3
+
+* Fix compatibility with wasm number semantics.
+
+## 0.5.2
+
+* Use the version `0.5.2` of `packge:test_api`.
+
+## 0.5.1
+
+* Start adding experimental support for native_assets.yaml, when
+  `--enable-experiment=native_assets` is passed.
+
+## 0.5.0
+
+* Support the `--compiler` flag, which can be used to configure which compiler
+  to use.
+  * To specify a compiler by platform, the argument supports platform selectors
+    through this syntax `[<platform>:]<compiler>`. For example the command line
+    argument `--compiler vm:source` would run all vm tests from source instead
+    of compiling to kernel first.
+  * If no given compiler is compatible for a platform, it will use its default
+    compiler instead.
+* Add support for `-c exe` (the native executable compiler) to the vm platform.
+* Add `Compiler` class, exposed through `backend.dart`.
+* Support compiler identifiers in platform selectors.
+* List the supported compilers for each platform in the usage text.
+* Update all reporters to print the compiler along with the platform name
+  when configured to print the platform. Extend the logic for printing platofrm
+  information to do so if any compilers are explicitly configured.
+* Deprecate `--use-data-isolate-strategy`. It is now an alias for `-c vm:source`
+  which is roughly equivalent. If this is breaking for you please file an issue.
+* **BREAKING** Add required `defaultCompiler` and `supportedCompilers` fields
+  to `Runtime`.
+* **BREAKING** Add required `compiler` field to `SuitePlatform`.
+* **BREAKING** Add required `compilerSelections` argument to some
+  `Configuration` and `SuiteConfiguration` constructors.
+* **BREAKING** Custom platform plugins need to respect the compiler option
+  given through the `SuitePlatform` argument to `PlatformPlugin.load`. This is
+  not statically breaking but it will be confusing for users if it isn't
+  supported.
+* **BREAKING** Remove `useDataIsolateStrategy` field from `Configuration`.
+* **BREAKING** Stop exporting APIs from `package:matcher/expect.dart`.
+
+## 0.4.24
+
+* Fix running paths by absolute path (with drive letter) on windows.
+
+## 0.4.23
 
 * Avoid empty expandable groups for tests without extra output in Github
   reporter.
+* Support running tests by absolute file uri.
+* Update `vm_service` constraint to `>=6.0.0 <12.0.0`.
 
-# 0.4.22
+## 0.4.22
 
 * Don't run `tearDown` until the test body and outstanding work is complete,
   even if the test has already failed.
 * Update `vm_service` constraint to `>=6.0.0 <11.0.0`.
 
-# 0.4.21
+## 0.4.21
 
 * Move `includeTags` and `excludeTags` from `SuiteConfiguration` to
   `Configuration`.
@@ -18,24 +89,24 @@
 * Fix VM tests which run after some test has changed the working directory.
   There are still issues with browser tests after changing directory.
 
-# 0.4.20
+## 0.4.20
 
 * Fix an issue with the github reporter where tests that fail asynchronously
   after they've completed would show up as succeeded tests.
 * Support the latest `package:test_api`.
 * Refactor `CompilerPool` to be abstract, add wasm compiler pool.
 
-# 0.4.19
+## 0.4.19
 
 * Support `package:matcher` version `0.12.13`.
 * Require Dart SDK version 2.18.
 
-# 0.4.18
+## 0.4.18
 
 * Support the latest `package:test_api`.
 * Support the latest `package:analyzer`.
 
-# 0.4.17
+## 0.4.17
 
 * Support the latest `package:test_api`.
 * Support the latest `package:frontend_server_client`.
diff --git a/pkgs/test_core/README.md b/pkgs/test_core/README.md
index 46d64fd..67f21a8 100644
--- a/pkgs/test_core/README.md
+++ b/pkgs/test_core/README.md
@@ -1,3 +1,6 @@
+[![pub package](https://img.shields.io/pub/v/test_core.svg)](https://pub.dev/packages/test_core)
+[![package publisher](https://img.shields.io/pub/publisher/test_core.svg)](https://pub.dev/packages/test_core/publisher)
+
 A minimal package for writing and running tests as well as extensions for
 implementing a custom test runner.
 
diff --git a/pkgs/test_core/lib/backend.dart b/pkgs/test_core/lib/backend.dart
index 3a1506b..69f6552 100644
--- a/pkgs/test_core/lib/backend.dart
+++ b/pkgs/test_core/lib/backend.dart
@@ -6,9 +6,8 @@
     'Please use package:test.')
 library test_core.backend;
 
-//ignore: deprecated_member_use
 export 'package:test_api/backend.dart'
-    show Metadata, PlatformSelector, Runtime, SuitePlatform;
+    show Compiler, Metadata, PlatformSelector, Runtime, SuitePlatform;
 
 export 'src/runner/configuration.dart' show Configuration;
 export 'src/runner/configuration/custom_runtime.dart' show CustomRuntime;
diff --git a/pkgs/test_core/lib/scaffolding.dart b/pkgs/test_core/lib/scaffolding.dart
index 40e6d56..b6719fe 100644
--- a/pkgs/test_core/lib/scaffolding.dart
+++ b/pkgs/test_core/lib/scaffolding.dart
@@ -10,7 +10,7 @@
 
 import 'package:meta/meta.dart' show isTest, isTestGroup;
 import 'package:path/path.dart' as p;
-import 'package:test_api/backend.dart'; //ignore: deprecated_member_use
+import 'package:test_api/backend.dart';
 import 'package:test_api/scaffolding.dart' show Timeout, pumpEventQueue;
 import 'package:test_api/src/backend/declarer.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/invoker.dart'; // ignore: implementation_imports
@@ -28,7 +28,7 @@
 // This file is an almost direct copy of import below, but with the global
 // declarer added.
 export 'package:test_api/scaffolding.dart'
-    hide test, group, setUp, setUpAll, tearDown, tearDownAll;
+    hide group, setUp, setUpAll, tearDown, tearDownAll, test;
 
 /// The global declarer.
 ///
@@ -54,8 +54,11 @@
   () async {
     await pumpEventQueue();
 
-    var suite = RunnerSuite(const PluginEnvironment(), SuiteConfiguration.empty,
-        _globalDeclarer!.build(), SuitePlatform(Runtime.vm, os: currentOSGuess),
+    var suite = RunnerSuite(
+        const PluginEnvironment(),
+        SuiteConfiguration.empty,
+        _globalDeclarer!.build(),
+        SuitePlatform(Runtime.vm, compiler: null, os: currentOSGuess),
         path: p.prettyUri(Uri.base));
 
     var engine = Engine();
@@ -130,11 +133,11 @@
 /// avoid this flag if possible and instead use the test runner flag `-n` to
 /// filter tests by name.
 @isTest
-void test(description, dynamic Function() body,
+void test(Object? description, dynamic Function() body,
     {String? testOn,
     Timeout? timeout,
-    skip,
-    tags,
+    Object? skip,
+    Object? tags,
     Map<String, dynamic>? onPlatform,
     int? retry,
     @Deprecated('Debug only') bool solo = false}) {
@@ -208,11 +211,11 @@
 /// avoid this flag if possible, and instead use the test runner flag `-n` to
 /// filter tests by name.
 @isTestGroup
-void group(description, dynamic Function() body,
+void group(Object? description, dynamic Function() body,
     {String? testOn,
     Timeout? timeout,
-    skip,
-    tags,
+    Object? skip,
+    Object? tags,
     Map<String, dynamic>? onPlatform,
     int? retry,
     @Deprecated('Debug only') bool solo = false}) {
diff --git a/pkgs/test_core/lib/src/bootstrap/vm.dart b/pkgs/test_core/lib/src/bootstrap/vm.dart
index d1eb59a..2166e7d 100644
--- a/pkgs/test_core/lib/src/bootstrap/vm.dart
+++ b/pkgs/test_core/lib/src/bootstrap/vm.dart
@@ -3,14 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:developer';
+import 'dart:io';
 import 'dart:isolate';
 
 import 'package:stream_channel/isolate_channel.dart';
 import 'package:stream_channel/stream_channel.dart';
 
 import 'package:test_core/src/runner/plugin/remote_platform_helpers.dart';
+import 'package:test_core/src/runner/plugin/shared_platform_helpers.dart';
 
-/// Bootstraps a vm test to communicate with the test runner.
+/// Bootstraps a vm test to communicate with the test runner over an isolate.
 void internalBootstrapVmTest(Function Function() getMain, SendPort sendPort) {
   var platformChannel =
       MultiChannel(IsolateChannel<Object?>.connectSend(sendPort));
@@ -24,3 +26,24 @@
     platformChannel.sink.add('done');
   });
 }
+
+/// Bootstraps a native executable test to communicate with the test runner over
+/// a socket.
+void internalBootstrapNativeTest(
+    Function Function() getMain, List<String> args) async {
+  if (args.length != 2) {
+    throw StateError(
+        'Expected exactly two args, a host and a port, but got $args');
+  }
+  var socket = await Socket.connect(args[0], int.parse(args[1]));
+  var platformChannel = MultiChannel<Object?>(jsonSocketStreamChannel(socket));
+  var testControlChannel = platformChannel.virtualChannel()
+    ..pipe(serializeSuite(getMain));
+  platformChannel.sink.add(testControlChannel.id);
+
+  platformChannel.stream.forEach((message) {
+    assert(message == 'debug');
+    debugger(message: 'Paused by test runner');
+    platformChannel.sink.add('done');
+  });
+}
diff --git a/pkgs/test_core/lib/src/direct_run.dart b/pkgs/test_core/lib/src/direct_run.dart
index f2b4e76..c574257 100644
--- a/pkgs/test_core/lib/src/direct_run.dart
+++ b/pkgs/test_core/lib/src/direct_run.dart
@@ -6,7 +6,7 @@
 import 'dart:collection';
 
 import 'package:path/path.dart' as p;
-import 'package:test_api/backend.dart'; //ignore: deprecated_member_use
+import 'package:test_api/backend.dart';
 import 'package:test_api/src/backend/declarer.dart'; //ignore: implementation_imports
 import 'package:test_api/src/backend/group.dart'; //ignore: implementation_imports
 import 'package:test_api/src/backend/group_entry.dart'; //ignore: implementation_imports
@@ -68,8 +68,11 @@
       allowDuplicateTestNames: allowDuplicateTestNames);
   await declarer.declare(testMain);
 
-  final suite = RunnerSuite(const PluginEnvironment(), SuiteConfiguration.empty,
-      declarer.build(), SuitePlatform(Runtime.vm, os: currentOSGuess),
+  final suite = RunnerSuite(
+      const PluginEnvironment(),
+      SuiteConfiguration.empty,
+      declarer.build(),
+      SuitePlatform(Runtime.vm, compiler: null, os: currentOSGuess),
       path: p.prettyUri(Uri.base));
 
   final engine = Engine()
diff --git a/pkgs/test_core/lib/src/executable.dart b/pkgs/test_core/lib/src/executable.dart
index 0c7530b..7b7978c 100644
--- a/pkgs/test_core/lib/src/executable.dart
+++ b/pkgs/test_core/lib/src/executable.dart
@@ -39,6 +39,7 @@
   completeShutdown();
 }
 
+// ignore: unreachable_from_main
 Future<void> runTests(List<String> args) async {
   await _execute(args);
 }
diff --git a/pkgs/test_core/lib/src/platform.dart b/pkgs/test_core/lib/src/platform.dart
index f1fc22b..af457b4 100644
--- a/pkgs/test_core/lib/src/platform.dart
+++ b/pkgs/test_core/lib/src/platform.dart
@@ -2,11 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// ignore: deprecated_member_use
-export 'package:test_api/backend.dart' show SuitePlatform, Runtime;
+export 'package:test_api/backend.dart' show Runtime, SuitePlatform;
 export 'package:test_core/src/runner/configuration.dart' show Configuration;
 export 'package:test_core/src/runner/environment.dart'
-    show PluginEnvironment, Environment;
+    show Environment, PluginEnvironment;
 export 'package:test_core/src/runner/hack_register_platform.dart'
     show registerPlatformPlugin;
 export 'package:test_core/src/runner/platform.dart' show PlatformPlugin;
diff --git a/pkgs/test_core/lib/src/runner.dart b/pkgs/test_core/lib/src/runner.dart
index ae7d6ee..c458b5d 100644
--- a/pkgs/test_core/lib/src/runner.dart
+++ b/pkgs/test_core/lib/src/runner.dart
@@ -7,9 +7,7 @@
 
 import 'package:async/async.dart';
 import 'package:boolean_selector/boolean_selector.dart';
-import 'package:path/path.dart' as p;
 import 'package:stack_trace/stack_trace.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/backend.dart'
     show PlatformSelector, Runtime, SuitePlatform;
 import 'package:test_api/src/backend/group.dart'; // ignore: implementation_imports
@@ -77,9 +75,11 @@
   /// Creates a new runner based on [configuration].
   factory Runner(Configuration config) => config.asCurrent(() {
         var engine = Engine(
-            concurrency: config.concurrency,
-            coverage: config.coverage,
-            testRandomizeOrderingSeed: config.testRandomizeOrderingSeed);
+          concurrency: config.concurrency,
+          coverage: config.coverage,
+          testRandomizeOrderingSeed: config.testRandomizeOrderingSeed,
+          stopOnFirstFailure: config.stopOnFirstFailure,
+        );
 
         var sinks = <IOSink>[];
         Reporter createFileReporter(String reporterName, String filepath) {
@@ -169,14 +169,15 @@
     var unsupportedRuntimes = _config.suiteDefaults.runtimes
         .map(_loader.findRuntime)
         .whereType<Runtime>()
-        .where((runtime) => !testOn.evaluate(currentPlatform(runtime)))
+        .where((runtime) => !testOn.evaluate(currentPlatform(runtime, null)))
         .toList();
+
     if (unsupportedRuntimes.isEmpty) return;
 
     // Human-readable names for all unsupported runtimes.
     var unsupportedNames = [];
 
-    // If the user tried to run on one or moe unsupported browsers, figure out
+    // If the user tried to run on one or more unsupported browsers, figure out
     // whether we should warn about the individual browsers or whether all
     // browsers are unsupported.
     var unsupportedBrowsers =
@@ -184,7 +185,7 @@
     if (unsupportedBrowsers.isNotEmpty) {
       var supportsAnyBrowser = _loader.allRuntimes
           .where((runtime) => runtime.isBrowser)
-          .any((runtime) => testOn.evaluate(currentPlatform(runtime)));
+          .any((runtime) => testOn.evaluate(currentPlatform(runtime, null)));
 
       if (supportsAnyBrowser) {
         unsupportedNames
@@ -197,8 +198,9 @@
     // If the user tried to run on the VM and it's not supported, figure out if
     // that's because of the current OS or whether the VM is unsupported.
     if (unsupportedRuntimes.contains(Runtime.vm)) {
-      var supportsAnyOS = OperatingSystem.all.any((os) => testOn
-          .evaluate(SuitePlatform(Runtime.vm, os: os, inGoogle: inGoogle)));
+      var supportsAnyOS = OperatingSystem.all.any((os) => testOn.evaluate(
+          SuitePlatform(Runtime.vm,
+              compiler: null, os: os, inGoogle: inGoogle)));
 
       if (supportsAnyOS) {
         unsupportedNames.add(currentOS.name);
@@ -317,7 +319,8 @@
                   'Cannot filter by line/column for this test suite, no suite'
                   'path available.');
             }
-            var absoluteSuitePath = p.absolute(path);
+            // The absolute path as it will appear in stack traces.
+            var absoluteSuitePath = File(path).absolute.uri.toFilePath();
 
             bool matchLineAndCol(Frame frame) {
               if (frame.uri.scheme != 'file' ||
diff --git a/pkgs/test_core/lib/src/runner/compiler_selection.dart b/pkgs/test_core/lib/src/runner/compiler_selection.dart
new file mode 100644
index 0000000..70ab553
--- /dev/null
+++ b/pkgs/test_core/lib/src/runner/compiler_selection.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:source_span/source_span.dart';
+import 'package:test_api/backend.dart';
+
+/// A compiler with which the user has chosen to run tests.
+class CompilerSelection {
+  /// The chosen compiler to use.
+  final Compiler compiler;
+
+  /// The location in the configuration file of this compiler string, or `null`
+  /// if it was defined outside a configuration file (for example, on the
+  /// command line).
+  final SourceSpan? span;
+
+  /// The platform selector for which platforms this compiler should apply to,
+  /// if specified. Defaults to all platforms where the compiler is supported.
+  final PlatformSelector? platformSelector;
+
+  CompilerSelection(String compiler,
+      {required this.platformSelector, required this.span})
+      : compiler = Compiler.builtIn.firstWhere((c) => c.identifier == compiler);
+
+  factory CompilerSelection.parse(String option, {SourceSpan? parentSpan}) {
+    var parts = option.split(':');
+    switch (parts.length) {
+      case 1:
+        _checkValidCompiler(option, parentSpan);
+        return CompilerSelection(option,
+            platformSelector: null, span: parentSpan);
+      case 2:
+        var compiler = parts[1];
+        _checkValidCompiler(compiler, parentSpan);
+        return CompilerSelection(compiler,
+            platformSelector: PlatformSelector.parse(parts[0]),
+            span: parentSpan);
+      default:
+        throw ArgumentError.value(
+            option,
+            '--compiler',
+            'Must be of the format [<boolean-selector>:]<compiler>, but got '
+                'more than one `:`.');
+    }
+  }
+
+  @override
+  bool operator ==(Object other) =>
+      other is CompilerSelection && other.compiler == compiler;
+
+  @override
+  int get hashCode => compiler.hashCode;
+}
+
+void _checkValidCompiler(String compiler, SourceSpan? span) {
+  if (Compiler.builtIn.any((c) => c.identifier == compiler)) return;
+  throw SourceSpanFormatException(
+      'Invalid compiler `$compiler`, must be one of ${Compiler.builtIn.map((c) => c.identifier).join(', ')}',
+      span);
+}
diff --git a/pkgs/test_core/lib/src/runner/configuration.dart b/pkgs/test_core/lib/src/runner/configuration.dart
index 008f989..12d3aa6 100644
--- a/pkgs/test_core/lib/src/runner/configuration.dart
+++ b/pkgs/test_core/lib/src/runner/configuration.dart
@@ -10,13 +10,12 @@
 import 'package:glob/glob.dart';
 import 'package:path/path.dart' as p;
 import 'package:source_span/source_span.dart';
-import 'package:test_api/scaffolding.dart' // ignore: deprecated_member_use
-    show
-        Timeout;
+import 'package:test_api/scaffolding.dart' show Timeout;
 import 'package:test_api/src/backend/platform_selector.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
 
 import '../util/io.dart';
+import 'compiler_selection.dart';
 import 'configuration/args.dart' as args;
 import 'configuration/custom_runtime.dart';
 import 'configuration/load.dart';
@@ -190,14 +189,6 @@
       });
   Set<String>? _knownPresets;
 
-  /// Whether to use the original `data:` URI isolate spawning strategy for VM
-  /// tests.
-  ///
-  /// This can make more sense than the default strategy in systems such as
-  /// `bazel` where only a single test suite is ran at a time.
-  bool get useDataIsolateStrategy => _useDataIsolateStrategy ?? false;
-  final bool? _useDataIsolateStrategy;
-
   /// Built-in runtimes whose settings are overridden by the user.
   final Map<String, RuntimeSettings> overrideRuntimes;
 
@@ -216,6 +207,11 @@
   /// The same seed will shuffle the tests in the same way every time.
   final int? testRandomizeOrderingSeed;
 
+  final bool? _stopOnFirstFailure;
+
+  /// Whether to stop running subsequent tests after a test fails.
+  bool get stopOnFirstFailure => _stopOnFirstFailure ?? false;
+
   /// Returns the current configuration, or a default configuration if no
   /// current configuration is set.
   ///
@@ -278,8 +274,8 @@
       required Map<String, RuntimeSettings>? overrideRuntimes,
       required Map<String, CustomRuntime>? defineRuntimes,
       required bool? noRetry,
-      required bool? useDataIsolateStrategy,
       required int? testRandomizeOrderingSeed,
+      required bool? stopOnFirstFailure,
 
       // Suite-level configuration
       required bool? allowDuplicateTestNames,
@@ -289,6 +285,7 @@
       required Iterable<String>? dart2jsArgs,
       required String? precompiledPath,
       required Iterable<Pattern>? globalPatterns,
+      required Iterable<CompilerSelection>? compilerSelections,
       required Iterable<RuntimeSelection>? runtimes,
       required BooleanSelector? includeTags,
       required BooleanSelector? excludeTags,
@@ -330,8 +327,8 @@
         overrideRuntimes: overrideRuntimes,
         defineRuntimes: defineRuntimes,
         noRetry: noRetry,
-        useDataIsolateStrategy: useDataIsolateStrategy,
         testRandomizeOrderingSeed: testRandomizeOrderingSeed,
+        stopOnFirstFailure: stopOnFirstFailure,
         includeTags: includeTags,
         excludeTags: excludeTags,
         globalPatterns: globalPatterns,
@@ -342,6 +339,7 @@
             runSkipped: runSkipped,
             dart2jsArgs: dart2jsArgs,
             precompiledPath: precompiledPath,
+            compilerSelections: compilerSelections,
             runtimes: runtimes,
             tags: tags,
             onPlatform: onPlatform,
@@ -387,8 +385,8 @@
           Map<String, RuntimeSettings>? overrideRuntimes,
           Map<String, CustomRuntime>? defineRuntimes,
           bool? noRetry,
-          bool? useDataIsolateStrategy,
           int? testRandomizeOrderingSeed,
+          bool? stopOnFirstFailure,
 
           // Suite-level configuration
           bool? allowDuplicateTestNames,
@@ -398,6 +396,7 @@
           Iterable<String>? dart2jsArgs,
           String? precompiledPath,
           Iterable<Pattern>? globalPatterns,
+          Iterable<CompilerSelection>? compilerSelections,
           Iterable<RuntimeSelection>? runtimes,
           BooleanSelector? includeTags,
           BooleanSelector? excludeTags,
@@ -438,8 +437,8 @@
           overrideRuntimes: overrideRuntimes,
           defineRuntimes: defineRuntimes,
           noRetry: noRetry,
-          useDataIsolateStrategy: useDataIsolateStrategy,
           testRandomizeOrderingSeed: testRandomizeOrderingSeed,
+          stopOnFirstFailure: stopOnFirstFailure,
           allowDuplicateTestNames: allowDuplicateTestNames,
           allowTestRandomization: allowTestRandomization,
           jsTrace: jsTrace,
@@ -447,6 +446,7 @@
           dart2jsArgs: dart2jsArgs,
           precompiledPath: precompiledPath,
           globalPatterns: globalPatterns,
+          compilerSelections: compilerSelections,
           runtimes: runtimes,
           includeTags: includeTags,
           excludeTags: excludeTags,
@@ -504,8 +504,8 @@
         overrideRuntimes: null,
         defineRuntimes: null,
         noRetry: null,
-        useDataIsolateStrategy: null,
         testRandomizeOrderingSeed: null,
+        stopOnFirstFailure: null,
         ignoreTimeouts: null,
         allowDuplicateTestNames: null,
         allowTestRandomization: null,
@@ -513,6 +513,7 @@
         dart2jsArgs: null,
         precompiledPath: null,
         globalPatterns: null,
+        compilerSelections: null,
         runtimes: null,
         includeTags: null,
         excludeTags: null,
@@ -571,13 +572,14 @@
         overrideRuntimes: null,
         defineRuntimes: null,
         noRetry: null,
-        useDataIsolateStrategy: null,
         testRandomizeOrderingSeed: null,
+        stopOnFirstFailure: null,
         jsTrace: null,
         runSkipped: null,
         dart2jsArgs: null,
         precompiledPath: null,
         globalPatterns: null,
+        compilerSelections: null,
         runtimes: null,
         includeTags: null,
         excludeTags: null,
@@ -604,6 +606,7 @@
           required String? reporter,
           required Map<String, String>? fileReporters,
           required int? concurrency,
+          required Iterable<CompilerSelection>? compilerSelections,
           required Iterable<RuntimeSelection>? runtimes,
           required Iterable<String>? chosenPresets,
           required Map<String, RuntimeSettings>? overrideRuntimes}) =>
@@ -614,6 +617,7 @@
         reporter: reporter,
         fileReporters: fileReporters,
         concurrency: concurrency,
+        compilerSelections: compilerSelections,
         runtimes: runtimes,
         chosenPresets: chosenPresets,
         overrideRuntimes: overrideRuntimes,
@@ -633,8 +637,8 @@
         presets: null,
         defineRuntimes: null,
         noRetry: null,
-        useDataIsolateStrategy: null,
         testRandomizeOrderingSeed: null,
+        stopOnFirstFailure: null,
         allowDuplicateTestNames: null,
         allowTestRandomization: null,
         jsTrace: null,
@@ -696,14 +700,15 @@
           presets: null,
           overrideRuntimes: null,
           noRetry: null,
-          useDataIsolateStrategy: null,
           testRandomizeOrderingSeed: null,
+          stopOnFirstFailure: null,
           allowDuplicateTestNames: null,
           allowTestRandomization: null,
           jsTrace: null,
           runSkipped: null,
           dart2jsArgs: null,
           precompiledPath: null,
+          compilerSelections: null,
           runtimes: null,
           tags: null,
           onPlatform: null,
@@ -761,8 +766,8 @@
       required Map<String, RuntimeSettings>? overrideRuntimes,
       required Map<String, CustomRuntime>? defineRuntimes,
       required bool? noRetry,
-      required bool? useDataIsolateStrategy,
       required this.testRandomizeOrderingSeed,
+      required bool? stopOnFirstFailure,
       required BooleanSelector? includeTags,
       required BooleanSelector? excludeTags,
       required Iterable<Pattern>? globalPatterns,
@@ -790,12 +795,12 @@
         overrideRuntimes = _map(overrideRuntimes),
         defineRuntimes = _map(defineRuntimes),
         _noRetry = noRetry,
-        _useDataIsolateStrategy = useDataIsolateStrategy,
         includeTags = includeTags ?? BooleanSelector.all,
         excludeTags = excludeTags ?? BooleanSelector.none,
         globalPatterns = globalPatterns == null
             ? const {}
             : UnmodifiableSetView(globalPatterns.toSet()),
+        _stopOnFirstFailure = stopOnFirstFailure,
         suiteDefaults = (() {
           var config = suiteDefaults ?? SuiteConfiguration.empty;
           if (pauseAfterLoad == true) {
@@ -848,8 +853,8 @@
         overrideRuntimes: null,
         defineRuntimes: null,
         noRetry: null,
-        useDataIsolateStrategy: null,
         testRandomizeOrderingSeed: null,
+        stopOnFirstFailure: null,
         includeTags: null,
         excludeTags: null,
       );
@@ -953,10 +958,9 @@
         defineRuntimes:
             mergeUnmodifiableMaps(defineRuntimes, other.defineRuntimes),
         noRetry: other._noRetry ?? _noRetry,
-        useDataIsolateStrategy:
-            other._useDataIsolateStrategy ?? _useDataIsolateStrategy,
         testRandomizeOrderingSeed:
             other.testRandomizeOrderingSeed ?? testRandomizeOrderingSeed,
+        stopOnFirstFailure: other._stopOnFirstFailure ?? _stopOnFirstFailure,
         includeTags: includeTags.intersection(other.includeTags),
         excludeTags: excludeTags.union(other.excludeTags),
         globalPatterns: globalPatterns.union(other.globalPatterns),
@@ -997,7 +1001,6 @@
       Map<String, RuntimeSettings>? overrideRuntimes,
       Map<String, CustomRuntime>? defineRuntimes,
       bool? noRetry,
-      bool? useDataIsolateStrategy,
       int? testRandomizeOrderingSeed,
       bool? ignoreTimeouts,
 
@@ -1046,10 +1049,9 @@
         overrideRuntimes: overrideRuntimes ?? this.overrideRuntimes,
         defineRuntimes: defineRuntimes ?? this.defineRuntimes,
         noRetry: noRetry ?? _noRetry,
-        useDataIsolateStrategy:
-            useDataIsolateStrategy ?? _useDataIsolateStrategy,
         testRandomizeOrderingSeed:
             testRandomizeOrderingSeed ?? this.testRandomizeOrderingSeed,
+        stopOnFirstFailure: _stopOnFirstFailure,
         includeTags: includeTags,
         excludeTags: excludeTags,
         globalPatterns: globalPatterns,
diff --git a/pkgs/test_core/lib/src/runner/configuration/args.dart b/pkgs/test_core/lib/src/runner/configuration/args.dart
index fcd2e89..5faa52d 100644
--- a/pkgs/test_core/lib/src/runner/configuration/args.dart
+++ b/pkgs/test_core/lib/src/runner/configuration/args.dart
@@ -7,12 +7,11 @@
 
 import 'package:args/args.dart';
 import 'package:boolean_selector/boolean_selector.dart';
-import 'package:test_api/scaffolding.dart' // ignore: deprecated_member_use
-    show
-        Timeout;
-import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
+import 'package:test_api/backend.dart';
+import 'package:test_api/scaffolding.dart' show Timeout;
 
 import '../../util/io.dart';
+import '../compiler_selection.dart';
 import '../configuration.dart';
 import '../runtime_selection.dart';
 import 'reporters.dart';
@@ -70,7 +69,20 @@
       abbr: 'p',
       help: 'The platform(s) on which to run the tests.\n'
           '[vm (default), '
-          '${allRuntimes.map((runtime) => runtime.identifier).join(", ")}]');
+          '${allRuntimes.map((runtime) => runtime.identifier).join(", ")}].\n'
+          'Each platform supports the following compilers:\n'
+          '${Runtime.vm.supportedCompilersText}\n'
+          '${allRuntimes.map((r) => r.supportedCompilersText).join('\n')}');
+  parser.addMultiOption('compiler',
+      abbr: 'c',
+      help: 'The compiler(s) to use to run tests, supported compilers are '
+          '[${Compiler.builtIn.map((c) => c.identifier).join(', ')}].\n'
+          'Each platform has a default compiler but may support other '
+          'compilers.\n'
+          'You can target a compiler to a specific platform using arguments '
+          'of the following form [<platform-selector>:]<compiler>.\n'
+          'If a platform is specified but no given compiler is supported for '
+          'that platform, then it will use its default compiler.');
   parser.addMultiOption('preset',
       abbr: 'P', help: 'The configuration preset(s) to use.');
   parser.addOption('concurrency',
@@ -112,10 +124,9 @@
       defaultsTo: false,
       negatable: false);
   parser.addFlag('use-data-isolate-strategy',
-      help: 'Use `data:` uri isolates when spawning VM tests instead of the\n'
-          'default strategy. This may be faster when you only ever run a\n'
-          'single test suite at a time.',
+      help: '**DEPRECATED**: This is now just an alias for --compiler source.',
       defaultsTo: false,
+      hide: true,
       negatable: false);
   parser.addOption('test-randomize-ordering-seed',
       help: 'Use the specified seed to randomize the execution order of test'
@@ -123,6 +134,8 @@
           'Must be a 32bit unsigned integer or "random".\n'
           'If "random", pick a random seed to use.\n'
           'If not passed, do not randomize test case execution order.');
+  parser.addFlag('fail-fast',
+      help: 'Stop running tests after the first failure.\n');
 
   var reporterDescriptions = <String, String>{};
   for (var reporter in allReporters.keys) {
@@ -177,41 +190,47 @@
 
 void _parseTestSelection(
     String option, Map<String, Set<TestSelection>> selections) {
-  var firstQuestion = option.indexOf('?');
-  TestSelection selection;
-  String path;
-  if (firstQuestion == -1) {
-    path = option;
-    selection = TestSelection();
-  } else if (option.substring(0, firstQuestion).contains('\\')) {
-    throw FormatException(
-        'When passing test path queries, you must pass the path in URI '
-        'format (use `/` for directory separators instead of `\\`).');
-  } else {
-    final uri = Uri.parse(option);
-
-    final names = uri.queryParametersAll['name'];
-    final fullName = uri.queryParameters['full-name'];
-    final line = uri.queryParameters['line'];
-    final col = uri.queryParameters['col'];
-
-    if (names != null && names.isNotEmpty && fullName != null) {
-      throw FormatException(
-        'Cannot specify both "name=<...>" and "full-name=<...>".',
-      );
+  if (Platform.isWindows) {
+    // If given a path that starts with what looks like a drive letter, convert it
+    // into a file scheme URI. We can't parse using `Uri.file` because we do
+    // support query parameters which aren't valid file uris.
+    if (option.indexOf(':') == 1) {
+      option = 'file:///$option';
     }
-    path = uri.path;
-    selection = TestSelection(
-      testPatterns: fullName != null
-          ? {RegExp('^${RegExp.escape(fullName)}\$')}
-          : {
-              if (names != null)
-                for (var name in names) RegExp(name)
-            },
-      line: line == null ? null : int.parse(line),
-      col: col == null ? null : int.parse(col),
+  }
+  final uri = Uri.parse(option);
+  // Decode the path segment. Specifically, on github actions back slashes on
+  // windows end up being encoded into the URI instead of converted into forward
+  // slashes.
+  var path = Uri.decodeComponent(uri.path);
+  // Strip out the leading slash before the drive letter on windows.
+  if (Platform.isWindows &&
+      path.startsWith('/') &&
+      path.length >= 3 &&
+      path[2] == ':') {
+    path = path.substring(1);
+  }
+
+  final names = uri.queryParametersAll['name'];
+  final fullName = uri.queryParameters['full-name'];
+  final line = uri.queryParameters['line'];
+  final col = uri.queryParameters['col'];
+
+  if (names != null && names.isNotEmpty && fullName != null) {
+    throw FormatException(
+      'Cannot specify both "name=<...>" and "full-name=<...>".',
     );
   }
+  final selection = TestSelection(
+    testPatterns: fullName != null
+        ? {RegExp('^${RegExp.escape(fullName)}\$')}
+        : {
+            if (names != null)
+              for (var name in names) RegExp(name)
+          },
+    line: line == null ? null : int.parse(line),
+    col: col == null ? null : int.parse(col),
+  );
 
   selections.update(path, (selections) => selections..add(selection),
       ifAbsent: () => {selection});
@@ -280,9 +299,15 @@
 
     var color = _ifParsed<bool>('color') ?? canUseSpecialChars;
 
-    var platform = _ifParsed<List<String>>('platform')
-        ?.map((runtime) => RuntimeSelection(runtime))
+    var runtimes =
+        _ifParsed<List<String>>('platform')?.map(RuntimeSelection.new).toList();
+    var compilerSelections = _ifParsed<List<String>>('compiler')
+        ?.map(CompilerSelection.parse)
         .toList();
+    if (_ifParsed('use-data-isolate-strategy') == true) {
+      compilerSelections ??= [];
+      compilerSelections.add(CompilerSelection.parse('vm:source'));
+    }
 
     final paths = _options.rest.isEmpty ? null : _options.rest;
 
@@ -313,18 +338,19 @@
         concurrency: _parseOption('concurrency', int.parse),
         shardIndex: shardIndex,
         totalShards: totalShards,
-        timeout: _parseOption('timeout', (value) => Timeout.parse(value)),
+        timeout: _parseOption('timeout', Timeout.parse),
         globalPatterns: patterns,
-        runtimes: platform,
+        compilerSelections: compilerSelections,
+        runtimes: runtimes,
         runSkipped: _ifParsed('run-skipped'),
         chosenPresets: _ifParsed('preset'),
         testSelections: selections,
         includeTags: includeTags,
         excludeTags: excludeTags,
         noRetry: _ifParsed('no-retry'),
-        useDataIsolateStrategy: _ifParsed('use-data-isolate-strategy'),
         testRandomizeOrderingSeed: testRandomizeOrderingSeed,
         ignoreTimeouts: _ifParsed('ignore-timeouts'),
+        stopOnFirstFailure: _ifParsed('fail-fast'),
         // Config that isn't supported on the command line
         addTags: null,
         allowTestRandomization: null,
@@ -392,3 +418,15 @@
     }
   }
 }
+
+extension _RuntimeDescription on Runtime {
+  String get supportedCompilersText {
+    var message = StringBuffer('[$identifier]: ');
+    message.write('${defaultCompiler.identifier} (default)');
+    for (var compiler in supportedCompilers) {
+      if (compiler == defaultCompiler) continue;
+      message.write(', ${compiler.identifier}');
+    }
+    return message.toString();
+  }
+}
diff --git a/pkgs/test_core/lib/src/runner/configuration/custom_runtime.dart b/pkgs/test_core/lib/src/runner/configuration/custom_runtime.dart
index 0c99191..d1bd028 100644
--- a/pkgs/test_core/lib/src/runner/configuration/custom_runtime.dart
+++ b/pkgs/test_core/lib/src/runner/configuration/custom_runtime.dart
@@ -7,7 +7,7 @@
 
 /// A user-defined test runtime, based on an existing runtime but with
 /// different configuration.
-class CustomRuntime {
+final class CustomRuntime {
   /// The human-friendly name of the runtime.
   final String name;
 
diff --git a/pkgs/test_core/lib/src/runner/configuration/load.dart b/pkgs/test_core/lib/src/runner/configuration/load.dart
index 6f4a35c..9284ae1 100644
--- a/pkgs/test_core/lib/src/runner/configuration/load.dart
+++ b/pkgs/test_core/lib/src/runner/configuration/load.dart
@@ -8,9 +8,7 @@
 import 'package:glob/glob.dart';
 import 'package:path/path.dart' as p;
 import 'package:source_span/source_span.dart';
-import 'package:test_api/scaffolding.dart' // ignore: deprecated_member_use
-    show
-        Timeout;
+import 'package:test_api/scaffolding.dart' show Timeout;
 import 'package:test_api/src/backend/operating_system.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/platform_selector.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/util/identifier_regex.dart'; // ignore: implementation_imports
@@ -19,6 +17,7 @@
 import '../../util/errors.dart';
 import '../../util/io.dart';
 import '../../util/pretty_print.dart';
+import '../compiler_selection.dart';
 import '../configuration.dart';
 import '../runtime_selection.dart';
 import '../suite.dart';
@@ -119,7 +118,7 @@
     var foldStackFrames = _loadFoldedStackFrames();
     var jsTrace = _getBool('js_trace');
 
-    var timeout = _parseValue('timeout', (value) => Timeout.parse(value));
+    var timeout = _parseValue('timeout', Timeout.parse);
 
     var onPlatform = _getMap('on_platform',
         key: (keyNode) => _parseNode(keyNode, 'on_platform key',
@@ -155,7 +154,7 @@
             foldTraceExcept: foldStackFrames['except'],
             foldTraceOnly: foldStackFrames['only'])
         .merge(_extractPresets<PlatformSelector>(
-            onPlatform, (map) => Configuration.onPlatform(map)));
+            onPlatform, Configuration.onPlatform));
 
     var osConfig = onOS[currentOS];
     return osConfig == null ? config : config.merge(osConfig);
@@ -195,8 +194,8 @@
         'add_tags', (tagNode) => _parseIdentifierLike(tagNode, 'Tag name'));
 
     var tags = _getMap('tags',
-        key: (keyNode) => _parseNode(
-            keyNode, 'tags key', (value) => BooleanSelector.parse(value)),
+        key: (keyNode) =>
+            _parseNode(keyNode, 'tags key', BooleanSelector.parse),
         value: (valueNode) =>
             _nestedConfig(valueNode, 'tag value', runnerConfig: false));
 
@@ -214,8 +213,7 @@
             addTags: addTags,
             allowTestRandomization: allowTestRandomization,
             allowDuplicateTestNames: allowDuplicateTestNames)
-        .merge(_extractPresets<BooleanSelector>(
-            tags, (map) => Configuration.tags(map)));
+        .merge(_extractPresets<BooleanSelector>(tags, Configuration.tags));
   }
 
   /// Loads runner configuration that's allowed in the global configuration
@@ -272,6 +270,14 @@
             _parseIdentifierLike(runtimeNode, 'Platform name'),
             runtimeNode.span));
 
+    var compilerSelections = _getList(
+        'compilers',
+        (node) => _parseNode(
+            node,
+            'compiler',
+            (option) =>
+                CompilerSelection.parse(option, parentSpan: node.span)));
+
     var chosenPresets = _getList('add_presets',
         (presetNode) => _parseIdentifierLike(presetNode, 'Preset name'));
 
@@ -286,6 +292,7 @@
         reporter: reporter,
         fileReporters: fileReporters,
         concurrency: concurrency,
+        compilerSelections: compilerSelections,
         runtimes: runtimes,
         chosenPresets: chosenPresets,
         overrideRuntimes: overrideRuntimes);
@@ -338,12 +345,12 @@
 
     var patterns = _getList('names', (nameNode) {
       _validate(nameNode, 'Names must be strings.', (value) => value is String);
-      return _parseNode(nameNode, 'name', (value) => RegExp(value));
+      return _parseNode(nameNode, 'name', RegExp.new);
     })
       ..addAll(_getList('plain_names', (nameNode) {
         _validate(
             nameNode, 'Names must be strings.', (value) => value is String);
-        return _parseNode(nameNode, 'name', (value) => RegExp(value));
+        return _parseNode(nameNode, 'name', RegExp.new);
       }));
 
     var paths = _getList('paths', (pathNode) {
@@ -353,7 +360,7 @@
       return _parseNode(pathNode, 'path', p.fromUri);
     });
 
-    var filename = _parseValue('filename', (value) => Glob(value));
+    var filename = _parseValue('filename', Glob.new);
 
     var includeTags = _parseBooleanSelector('include_tags');
     var excludeTags = _parseBooleanSelector('exclude_tags');
@@ -541,7 +548,7 @@
 
   /// Parses [node]'s value as a boolean selector.
   BooleanSelector? _parseBooleanSelector(String name) =>
-      _parseValue(name, (value) => BooleanSelector.parse(value));
+      _parseValue(name, BooleanSelector.parse);
 
   /// Parses [node]'s value as a platform selector.
   PlatformSelector? _parsePlatformSelector(String field) {
diff --git a/pkgs/test_core/lib/src/runner/configuration/reporters.dart b/pkgs/test_core/lib/src/runner/configuration/reporters.dart
index 2a724aa..d52f163 100644
--- a/pkgs/test_core/lib/src/runner/configuration/reporters.dart
+++ b/pkgs/test_core/lib/src/runner/configuration/reporters.dart
@@ -36,20 +36,23 @@
           color: config.color,
           printPath: config.testSelections.length > 1 ||
               Directory(config.testSelections.keys.single).existsSync(),
-          printPlatform: config.suiteDefaults.runtimes.length > 1)),
+          printPlatform: config.suiteDefaults.runtimes.length > 1 ||
+              config.suiteDefaults.compilerSelections != null)),
   'compact': ReporterDetails(
       'A single line, updated continuously.',
       (config, engine, sink) => CompactReporter.watch(engine, sink,
           color: config.color,
           printPath: config.testSelections.length > 1 ||
               Directory(config.testSelections.keys.single).existsSync(),
-          printPlatform: config.suiteDefaults.runtimes.length > 1)),
+          printPlatform: config.suiteDefaults.runtimes.length > 1 ||
+              config.suiteDefaults.compilerSelections != null)),
   'github': ReporterDetails(
       'A custom reporter for GitHub Actions (the default reporter when running on GitHub Actions).',
       (config, engine, sink) => GithubReporter.watch(engine, sink,
           printPath: config.testSelections.length > 1 ||
               Directory(config.testSelections.keys.single).existsSync(),
-          printPlatform: config.suiteDefaults.runtimes.length > 1)),
+          printPlatform: config.suiteDefaults.runtimes.length > 1 ||
+              config.suiteDefaults.compilerSelections != null)),
   'json': ReporterDetails(
       'A machine-readable format (see '
       'https://dart.dev/go/test-docs/json_reporter.md).',
diff --git a/pkgs/test_core/lib/src/runner/configuration/runtime_settings.dart b/pkgs/test_core/lib/src/runner/configuration/runtime_settings.dart
index 6e910a3..e366b4d 100644
--- a/pkgs/test_core/lib/src/runner/configuration/runtime_settings.dart
+++ b/pkgs/test_core/lib/src/runner/configuration/runtime_settings.dart
@@ -8,7 +8,7 @@
 import '../plugin/customizable_platform.dart';
 
 /// User-defined settings for a built-in test runtime.
-class RuntimeSettings {
+final class RuntimeSettings {
   /// The identifier used to look up the runtime being overridden.
   final String identifier;
 
diff --git a/pkgs/test_core/lib/src/runner/engine.dart b/pkgs/test_core/lib/src/runner/engine.dart
index 578a6bf..665fd60 100644
--- a/pkgs/test_core/lib/src/runner/engine.dart
+++ b/pkgs/test_core/lib/src/runner/engine.dart
@@ -69,6 +69,9 @@
   /// The same seed will shuffle the tests in the same way every time.
   int? testRandomizeOrderingSeed;
 
+  /// Whether to stop running tests after a failure.
+  bool _stopOnFirstFailure;
+
   /// A pool that limits the number of test suites running concurrently.
   final Pool _runPool;
 
@@ -202,8 +205,16 @@
   /// Omitting this argument or passing `0` disables shuffling.
   ///
   /// [coverage] specifies a directory to output coverage information.
-  Engine({int? concurrency, String? coverage, this.testRandomizeOrderingSeed})
-      : _runPool = Pool(concurrency ?? 1),
+  ///
+  /// If [stopOnFirstFailure] then a single failing test will cause the engine
+  /// to [close] and stop ruunning further tests.
+  Engine({
+    int? concurrency,
+    String? coverage,
+    this.testRandomizeOrderingSeed,
+    bool stopOnFirstFailure = false,
+  })  : _runPool = Pool(concurrency ?? 1),
+        _stopOnFirstFailure = stopOnFirstFailure,
         _coverage = coverage {
     _group.future.then((_) {
       _onTestStartedGroup.close();
@@ -222,8 +233,12 @@
   /// [concurrency] controls how many suites are run at once. If [runSkipped] is
   /// `true`, skipped tests will be run as though they weren't skipped.
   factory Engine.withSuites(List<RunnerSuite> suites,
-      {int? concurrency, String? coverage}) {
-    var engine = Engine(concurrency: concurrency, coverage: coverage);
+      {int? concurrency, String? coverage, bool stopOnFirstFailure = false}) {
+    var engine = Engine(
+      concurrency: concurrency,
+      coverage: coverage,
+      stopOnFirstFailure: stopOnFirstFailure,
+    );
     for (var suite in suites) {
       engine.suiteSink.add(suite);
     }
@@ -371,7 +386,10 @@
     // loop pump to avoid starving non-microtask events.
     await Future(() {});
 
-    if (!_restarted.contains(liveTest)) return;
+    if (!_restarted.contains(liveTest)) {
+      if (_stopOnFirstFailure && liveTest.state.result.isFailing) close();
+      return;
+    }
     await _runLiveTest(suiteController, liveTest.copy(),
         countSuccess: countSuccess);
     _restarted.remove(liveTest);
diff --git a/pkgs/test_core/lib/src/runner/hybrid_listener.dart b/pkgs/test_core/lib/src/runner/hybrid_listener.dart
index f7fdb86..bf2daa2 100644
--- a/pkgs/test_core/lib/src/runner/hybrid_listener.dart
+++ b/pkgs/test_core/lib/src/runner/hybrid_listener.dart
@@ -9,7 +9,6 @@
 import 'package:stack_trace/stack_trace.dart';
 import 'package:stream_channel/isolate_channel.dart';
 import 'package:stream_channel/stream_channel.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/backend.dart' show RemoteException;
 import 'package:test_api/src/utils.dart'; // ignore: implementation_imports
 
diff --git a/pkgs/test_core/lib/src/runner/load_suite.dart b/pkgs/test_core/lib/src/runner/load_suite.dart
index 2c64fc0..db6b12e 100644
--- a/pkgs/test_core/lib/src/runner/load_suite.dart
+++ b/pkgs/test_core/lib/src/runner/load_suite.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 
 import 'package:stack_trace/stack_trace.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/scaffolding.dart' show Timeout;
 import 'package:test_api/src/backend/group.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/invoker.dart'; // ignore: implementation_imports
@@ -136,7 +135,7 @@
     return LoadSuite(
         'loading ${exception.path}',
         config ?? SuiteConfiguration.empty,
-        platform ?? currentPlatform(Runtime.vm),
+        platform ?? currentPlatform(Runtime.vm, null),
         () => Future.error(exception, stackTrace),
         path: exception.path);
   }
diff --git a/pkgs/test_core/lib/src/runner/loader.dart b/pkgs/test_core/lib/src/runner/loader.dart
index 6cd47d2..b3ec7e8 100644
--- a/pkgs/test_core/lib/src/runner/loader.dart
+++ b/pkgs/test_core/lib/src/runner/loader.dart
@@ -11,6 +11,7 @@
 import 'package:test_api/src/backend/group.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/invoker.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
+import 'package:test_core/src/runner/compiler_selection.dart';
 import 'package:yaml/yaml.dart';
 
 import '../util/io.dart';
@@ -64,7 +65,7 @@
   /// Creates a new loader that loads tests on platforms defined in
   /// [Configuration.current].
   Loader() {
-    _registerPlatformPlugin([Runtime.vm], () => VMPlatform());
+    _registerPlatformPlugin([Runtime.vm], VMPlatform.new);
 
     platformCallbacks.forEach((runtime, plugin) {
       _registerPlatformPlugin([runtime], plugin);
@@ -182,60 +183,67 @@
 
     for (var runtimeName in suiteConfig.runtimes) {
       var runtime = findRuntime(runtimeName);
-      assert(runtime != null, 'Unknown platform "$runtimeName".');
-
-      var platform = currentPlatform(runtime!);
-      if (!suiteConfig.metadata.testOn.evaluate(platform)) {
-        continue;
+      if (runtime == null) {
+        throw ArgumentError.value(runtimeName, 'platform', 'Unknown platform');
       }
+      final compilers = {
+        for (var selection
+            in suiteConfig.compilerSelections ?? <CompilerSelection>[])
+          if (runtime.supportedCompilers.contains(selection.compiler) &&
+              (selection.platformSelector == null ||
+                  selection.platformSelector!
+                      .evaluate(currentPlatform(runtime, selection.compiler))))
+            selection.compiler,
+      };
+      if (compilers.isEmpty) compilers.add(runtime.defaultCompiler);
 
-      var platformConfig = suiteConfig.forPlatform(platform);
+      for (var compiler in compilers) {
+        var platform = currentPlatform(runtime, compiler);
+        if (!suiteConfig.metadata.testOn.evaluate(platform)) continue;
 
-      // Don't load a skipped suite.
-      if (platformConfig.metadata.skip && !platformConfig.runSkipped) {
-        yield LoadSuite.forSuite(RunnerSuite(
-            const PluginEnvironment(),
-            platformConfig,
-            Group.root([LocalTest('(suite)', platformConfig.metadata, () {})],
-                metadata: platformConfig.metadata),
-            platform,
-            path: path));
-        continue;
-      }
+        var platformConfig = suiteConfig.forPlatform(platform);
 
-      var name =
-          (platform.runtime.isJS && platformConfig.precompiledPath == null
-                  ? 'compiling '
-                  : 'loading ') +
-              path;
-      yield LoadSuite(name, platformConfig, platform, () async {
-        var memo = _platformPlugins[platform.runtime]!;
-
-        var retriesLeft = suiteConfig.metadata.retry;
-        while (true) {
-          try {
-            var plugin =
-                await memo.runOnce(_platformCallbacks[platform.runtime]!);
-            _customizePlatform(plugin, platform.runtime);
-            var suite = await plugin.load(path, platform, platformConfig,
-                {'platformVariables': _runtimeVariables.toList()});
-            if (suite != null) _suites.add(suite);
-            return suite;
-          } on Object catch (error, stackTrace) {
-            if (retriesLeft > 0) {
-              retriesLeft--;
-              print('Retrying load of $path in 1s ($retriesLeft remaining)');
-              await Future.delayed(Duration(seconds: 1));
-              continue;
-            }
-            if (error is LoadException) {
-              rethrow;
-            }
-            await Future.error(LoadException(path, error), stackTrace);
-            return null;
-          }
+        // Don't load a skipped suite.
+        if (platformConfig.metadata.skip && !platformConfig.runSkipped) {
+          yield LoadSuite.forSuite(RunnerSuite(
+              const PluginEnvironment(),
+              platformConfig,
+              Group.root([LocalTest('(suite)', platformConfig.metadata, () {})],
+                  metadata: platformConfig.metadata),
+              platform,
+              path: path));
+          continue;
         }
-      }, path: path);
+
+        yield LoadSuite('loading $path', platformConfig, platform, () async {
+          var memo = _platformPlugins[platform.runtime]!;
+
+          var retriesLeft = suiteConfig.metadata.retry;
+          while (true) {
+            try {
+              var plugin =
+                  await memo.runOnce(_platformCallbacks[platform.runtime]!);
+              _customizePlatform(plugin, platform.runtime);
+              var suite = await plugin.load(path, platform, platformConfig,
+                  {'platformVariables': _runtimeVariables.toList()});
+              if (suite != null) _suites.add(suite);
+              return suite;
+            } on Object catch (error, stackTrace) {
+              if (retriesLeft > 0) {
+                retriesLeft--;
+                print('Retrying load of $path in 1s ($retriesLeft remaining)');
+                await Future.delayed(Duration(seconds: 1));
+                continue;
+              }
+              if (error is LoadException) {
+                rethrow;
+              }
+              await Future.error(LoadException(path, error), stackTrace);
+              return null;
+            }
+          }
+        }, path: path);
+      }
     }
   }
 
diff --git a/pkgs/test_core/lib/src/runner/parse_metadata.dart b/pkgs/test_core/lib/src/runner/parse_metadata.dart
index 451f175..63b5e59 100644
--- a/pkgs/test_core/lib/src/runner/parse_metadata.dart
+++ b/pkgs/test_core/lib/src/runner/parse_metadata.dart
@@ -6,9 +6,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:path/path.dart' as p;
 import 'package:source_span/source_span.dart';
-import 'package:test_api/scaffolding.dart' // ignore: deprecated_member_use
-    show
-        Timeout;
+import 'package:test_api/scaffolding.dart' show Timeout;
 import 'package:test_api/src/backend/metadata.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/platform_selector.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/util/identifier_regex.dart'; // ignore: implementation_imports
@@ -200,9 +198,8 @@
   ///
   /// [annotation] is the annotation.
   Map<PlatformSelector, Metadata> _parseOnPlatform(Annotation annotation) {
-    return _parseMap(annotation.arguments!.arguments.first, key: (key) {
-      return _parsePlatformSelector(key);
-    }, value: (value) {
+    return _parseMap(annotation.arguments!.arguments.first,
+        key: _parsePlatformSelector, value: (value) {
       var expressions = <AstNode>[];
       if (value is ListLiteral) {
         expressions = _parseList(value);
@@ -219,10 +216,7 @@
       Object? skip;
       for (var expression in expressions) {
         if (expression is InstanceCreationExpression) {
-          var className = _resolveConstructor(
-                  expression.constructorName.type.name,
-                  expression.constructorName.name)
-              .first;
+          var className = expression.constructorName.type.name2.lexeme;
 
           if (className == 'Timeout') {
             _assertSingle(timeout, 'Timeout', expression);
@@ -345,7 +339,7 @@
   /// If [expression] is not an instantiation of a [className] throws.
   String? _findConstructorName(Expression expression, String className) {
     if (expression is InstanceCreationExpression) {
-      return _findConstructornameFromInstantiation(expression, className);
+      return _findConstructorNameFromInstantiation(expression, className);
     }
     if (expression is MethodInvocation) {
       return _findConstructorNameFromMethod(expression, className);
@@ -354,12 +348,10 @@
         'Expected a $className.', _spanFor(expression));
   }
 
-  String? _findConstructornameFromInstantiation(
+  String? _findConstructorNameFromInstantiation(
       InstanceCreationExpression constructor, String className) {
-    var pair = _resolveConstructor(constructor.constructorName.type.name,
-        constructor.constructorName.name);
-    var actualClassName = pair.first;
-    var constructorName = pair.last;
+    var actualClassName = constructor.constructorName.type.name2.lexeme;
+    var constructorName = constructor.constructorName.name?.name;
 
     if (actualClassName != className) {
       throw SourceSpanFormatException(
diff --git a/pkgs/test_core/lib/src/runner/plugin/platform_helpers.dart b/pkgs/test_core/lib/src/runner/plugin/platform_helpers.dart
index f40a71c..569ef60 100644
--- a/pkgs/test_core/lib/src/runner/plugin/platform_helpers.dart
+++ b/pkgs/test_core/lib/src/runner/plugin/platform_helpers.dart
@@ -7,7 +7,6 @@
 
 import 'package:stack_trace/stack_trace.dart';
 import 'package:stream_channel/stream_channel.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/backend.dart'
     show Metadata, RemoteException, SuitePlatform;
 import 'package:test_api/src/backend/group.dart'; // ignore: implementation_imports
@@ -63,7 +62,7 @@
     'foldTraceOnly': Configuration.current.foldTraceOnly.toList(),
     'allowDuplicateTestNames': suiteConfig.allowDuplicateTestNames,
     'ignoreTimeouts': suiteConfig.ignoreTimeouts,
-    ...(message as Map<String, dynamic>),
+    ...message as Map<String, dynamic>,
   });
 
   var completer = Completer<Group>();
@@ -95,7 +94,8 @@
             break;
 
           case 'error':
-            var asyncError = RemoteException.deserialize(response['error']);
+            var asyncError = RemoteException.deserialize(
+                response['error'] as Map<String, dynamic>);
             handleError(
                 LoadException(path, asyncError.error), asyncError.stackTrace);
             break;
@@ -156,7 +156,7 @@
     var metadata = Metadata.deserialize(test['metadata']);
     var trace =
         test['trace'] == null ? null : Trace.parse(test['trace'] as String);
-    var testChannel = _channel.virtualChannel(test['channel'] as int);
+    var testChannel = _channel.virtualChannel((test['channel'] as num).toInt());
     return RunnerTest(test['name'] as String, metadata, trace, testChannel);
   }
 }
diff --git a/pkgs/test_core/lib/src/runner/plugin/remote_platform_helpers.dart b/pkgs/test_core/lib/src/runner/plugin/remote_platform_helpers.dart
index 7e50207..8eb2b76 100644
--- a/pkgs/test_core/lib/src/runner/plugin/remote_platform_helpers.dart
+++ b/pkgs/test_core/lib/src/runner/plugin/remote_platform_helpers.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:stream_channel/stream_channel.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/backend.dart'
     show RemoteListener, StackTraceFormatter, StackTraceMapper;
 
diff --git a/pkgs/test_core/lib/src/runner/plugin/shared_platform_helpers.dart b/pkgs/test_core/lib/src/runner/plugin/shared_platform_helpers.dart
new file mode 100644
index 0000000..4fdcf23
--- /dev/null
+++ b/pkgs/test_core/lib/src/runner/plugin/shared_platform_helpers.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:async/async.dart';
+import 'package:stream_channel/stream_channel.dart';
+
+/// Converts a raw [Socket] into a [StreamChannel] of JSON objects.
+///
+/// JSON messages are separated by newlines.
+StreamChannel<Object?> jsonSocketStreamChannel(Socket socket) =>
+    StreamChannel.withGuarantees(socket, socket)
+        .cast<List<int>>()
+        .transform(StreamChannelTransformer.fromCodec(utf8))
+        .transformStream(const LineSplitter())
+        .transformSink(StreamSinkTransformer.fromHandlers(
+            handleData: (original, sink) => sink.add('$original\n')))
+        .transform(jsonDocument);
diff --git a/pkgs/test_core/lib/src/runner/reporter/compact.dart b/pkgs/test_core/lib/src/runner/reporter/compact.dart
index 6760a91..962213f 100644
--- a/pkgs/test_core/lib/src/runner/reporter/compact.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/compact.dart
@@ -435,7 +435,8 @@
     }
 
     if (_printPlatform) {
-      name = '[${liveTest.suite.platform.runtime.name}] $name';
+      name = '[${liveTest.suite.platform.runtime.name}, '
+          '${liveTest.suite.platform.compiler.name}] $name';
     }
 
     if (liveTest.suite is LoadSuite) name = '$_bold$_gray$name$_noColor';
diff --git a/pkgs/test_core/lib/src/runner/reporter/expanded.dart b/pkgs/test_core/lib/src/runner/reporter/expanded.dart
index 6ff2b6f..a654528 100644
--- a/pkgs/test_core/lib/src/runner/reporter/expanded.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/expanded.dart
@@ -171,9 +171,9 @@
     } else if (_engine.active.isEmpty &&
         _engine.activeSuiteLoads.length == 1 &&
         _engine.activeSuiteLoads.first == liveTest &&
-        liveTest.test.name.startsWith('compiling ')) {
-      // Print a progress line for load tests that come from compiling JS, since
-      // that takes a long time.
+        liveTest.test.name.startsWith('loading ')) {
+      // Print a progress line for ongoing suite loading synthetic test since it
+      // may be slow (or stuck) depending on the platform.
       _progressLine(_description(liveTest));
     }
 
@@ -336,7 +336,8 @@
     }
 
     if (_printPlatform) {
-      name = '[${liveTest.suite.platform.runtime.name}] $name';
+      name = '[${liveTest.suite.platform.runtime.name}, '
+          '${liveTest.suite.platform.compiler.name}] $name';
     }
 
     if (liveTest.suite is LoadSuite) name = '$_bold$_gray$name$_noColor';
diff --git a/pkgs/test_core/lib/src/runner/reporter/github.dart b/pkgs/test_core/lib/src/runner/reporter/github.dart
index ed9ab5a..5249817 100644
--- a/pkgs/test_core/lib/src/runner/reporter/github.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/github.dart
@@ -152,7 +152,8 @@
       }
     }
     if (_printPlatform) {
-      name = '[${test.suite.platform.runtime.name}] $name';
+      name = '[${test.suite.platform.runtime.name}, '
+          '${test.suite.platform.compiler.name}] $name';
     }
     if (messages.isEmpty && errors.isEmpty) {
       _sink.writeln('$prefix $name$statusSuffix');
@@ -184,7 +185,8 @@
         }
       }
       if (_printPlatform) {
-        name = '[${test.suite.platform.runtime.name}] $name';
+        name = '[${test.suite.platform.runtime.name}, '
+            '${test.suite.platform.compiler.name}] $name';
       }
 
       _sink.writeln(_GithubMarkup.startGroup('$prefix $name$statusSuffix'));
diff --git a/pkgs/test_core/lib/src/runner/reporter/json.dart b/pkgs/test_core/lib/src/runner/reporter/json.dart
index 5497817..0683b60 100644
--- a/pkgs/test_core/lib/src/runner/reporter/json.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/json.dart
@@ -303,7 +303,7 @@
   /// all be `null`.
   Map<String, dynamic> _frameInfo(SuiteConfiguration suiteConfig, Trace? trace,
       Runtime runtime, String suitePath) {
-    var absoluteSuitePath = p.absolute(suitePath);
+    var absoluteSuitePath = p.canonicalize(p.absolute(suitePath));
     var frame = trace?.frames.first;
     if (frame == null || (suiteConfig.jsTrace && runtime.isJS)) {
       return {'line': null, 'column': null, 'url': null};
@@ -311,7 +311,7 @@
 
     var rootFrame = trace?.frames.firstWhereOrNull((frame) =>
         frame.uri.scheme == 'file' &&
-        frame.uri.toFilePath() == absoluteSuitePath);
+        p.canonicalize(frame.uri.toFilePath()) == absoluteSuitePath);
     return {
       'line': frame.line,
       'column': frame.column,
diff --git a/pkgs/test_core/lib/src/runner/runner_test.dart b/pkgs/test_core/lib/src/runner/runner_test.dart
index 10ef8bc..f140c01 100644
--- a/pkgs/test_core/lib/src/runner/runner_test.dart
+++ b/pkgs/test_core/lib/src/runner/runner_test.dart
@@ -6,7 +6,6 @@
 
 import 'package:stack_trace/stack_trace.dart';
 import 'package:stream_channel/stream_channel.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/backend.dart'
     show Metadata, RemoteException, SuitePlatform;
 import 'package:test_api/src/backend/group.dart'; // ignore: implementation_imports
@@ -46,7 +45,8 @@
       testChannel.stream.listen((message) {
         switch (message['type'] as String) {
           case 'error':
-            var asyncError = RemoteException.deserialize(message['error']);
+            var asyncError = RemoteException.deserialize(
+                message['error'] as Map<String, dynamic>);
             var stackTrace = asyncError.stackTrace;
             controller.addError(asyncError.error, stackTrace);
             break;
@@ -71,7 +71,8 @@
             // this virtual channel and cause the spawned isolate to close as
             // well.
             spawnHybridUri(message['url'] as String, message['message'], suite)
-                .pipe(testChannel.virtualChannel(message['channel'] as int));
+                .pipe(testChannel
+                    .virtualChannel((message['channel'] as num).toInt()));
             break;
         }
       }, onDone: () {
diff --git a/pkgs/test_core/lib/src/runner/runtime_selection.dart b/pkgs/test_core/lib/src/runner/runtime_selection.dart
index e607400..7f64a5c 100644
--- a/pkgs/test_core/lib/src/runner/runtime_selection.dart
+++ b/pkgs/test_core/lib/src/runner/runtime_selection.dart
@@ -17,7 +17,8 @@
   RuntimeSelection(this.name, [this.span]);
 
   @override
-  bool operator ==(other) => other is RuntimeSelection && other.name == name;
+  bool operator ==(Object other) =>
+      other is RuntimeSelection && other.name == name;
 
   @override
   int get hashCode => name.hashCode;
diff --git a/pkgs/test_core/lib/src/runner/spawn_hybrid.dart b/pkgs/test_core/lib/src/runner/spawn_hybrid.dart
index e21b8f8..e44e05d 100644
--- a/pkgs/test_core/lib/src/runner/spawn_hybrid.dart
+++ b/pkgs/test_core/lib/src/runner/spawn_hybrid.dart
@@ -10,7 +10,6 @@
 import 'package:path/path.dart' as p;
 import 'package:stream_channel/isolate_channel.dart';
 import 'package:stream_channel/stream_channel.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/backend.dart' show RemoteException;
 import 'package:test_api/src/backend/suite.dart'; // ignore: implementation_imports
 
@@ -160,15 +159,9 @@
   return '';
 }
 
-Future<String> _readUri(Uri uri) async {
-  switch (uri.scheme) {
-    case '':
-    case 'file':
-      return File.fromUri(uri).readAsString();
-    case 'data':
-      return uri.data!.contentAsString();
-    default:
-      throw ArgumentError.value(uri, 'uri',
-          'Only data and file uris (as well as relative paths) are supported');
-  }
-}
+Future<String> _readUri(Uri uri) async => switch (uri.scheme) {
+      '' || 'file' => await File.fromUri(uri).readAsString(),
+      'data' => uri.data!.contentAsString(),
+      _ => throw ArgumentError.value(uri, 'uri',
+          'Only data and file uris (as well as relative paths) are supported'),
+    };
diff --git a/pkgs/test_core/lib/src/runner/suite.dart b/pkgs/test_core/lib/src/runner/suite.dart
index 138abee..b3561ab 100644
--- a/pkgs/test_core/lib/src/runner/suite.dart
+++ b/pkgs/test_core/lib/src/runner/suite.dart
@@ -5,14 +5,13 @@
 import 'package:boolean_selector/boolean_selector.dart';
 import 'package:collection/collection.dart';
 import 'package:source_span/source_span.dart';
-import 'package:test_api/scaffolding.dart' // ignore: deprecated_member_use
-    show
-        Timeout;
+import 'package:test_api/scaffolding.dart' show Timeout;
 import 'package:test_api/src/backend/metadata.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/platform_selector.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/suite_platform.dart'; // ignore: implementation_imports
 
+import 'compiler_selection.dart';
 import 'runtime_selection.dart';
 
 /// A filter on tests cases to run within a test suite.
@@ -22,7 +21,7 @@
 /// matches any test selection.
 ///
 /// An empty [TestSelection()] will run all tests in the suite.
-class TestSelection {
+final class TestSelection {
   /// The patterns to check against test case names.
   ///
   /// Only run tests which match all the patterns.
@@ -40,7 +39,7 @@
 /// Suite-level configuration.
 ///
 /// This tracks configuration that can differ from suite to suite.
-class SuiteConfiguration {
+final class SuiteConfiguration {
   /// Empty configuration with only default values.
   ///
   /// Using this is slightly more efficient than manually constructing a new
@@ -54,6 +53,7 @@
       testSelections: const {},
       precompiledPath: null,
       runtimes: null,
+      compilerSelections: null,
       tags: null,
       onPlatform: null,
       metadata: null,
@@ -104,6 +104,9 @@
   /// [testSelections].
   final Set<TestSelection> testSelections;
 
+  /// The set of compiler selections for running tests.
+  final List<CompilerSelection>? compilerSelections;
+
   /// The set of runtimes on which to run tests.
   List<String> get runtimes => _runtimes == null
       ? const ['vm']
@@ -153,6 +156,7 @@
       required bool? runSkipped,
       required Iterable<String>? dart2jsArgs,
       required String? precompiledPath,
+      required Iterable<CompilerSelection>? compilerSelections,
       required Iterable<RuntimeSelection>? runtimes,
       required Map<BooleanSelector, SuiteConfiguration>? tags,
       required Map<PlatformSelector, SuiteConfiguration>? onPlatform,
@@ -175,6 +179,7 @@
         dart2jsArgs: dart2jsArgs,
         testSelections: const {},
         precompiledPath: precompiledPath,
+        compilerSelections: compilerSelections,
         runtimes: runtimes,
         tags: tags,
         onPlatform: onPlatform,
@@ -202,6 +207,7 @@
           bool? runSkipped,
           Iterable<String>? dart2jsArgs,
           String? precompiledPath,
+          Iterable<CompilerSelection>? compilerSelections,
           Iterable<RuntimeSelection>? runtimes,
           Map<BooleanSelector, SuiteConfiguration>? tags,
           Map<PlatformSelector, SuiteConfiguration>? onPlatform,
@@ -223,6 +229,7 @@
           runSkipped: runSkipped,
           dart2jsArgs: dart2jsArgs,
           precompiledPath: precompiledPath,
+          compilerSelections: compilerSelections,
           runtimes: runtimes,
           tags: tags,
           onPlatform: onPlatform,
@@ -260,6 +267,7 @@
     required Iterable<String>? dart2jsArgs,
     required this.testSelections,
     required this.precompiledPath,
+    required Iterable<CompilerSelection>? compilerSelections,
     required Iterable<RuntimeSelection>? runtimes,
     required Map<BooleanSelector, SuiteConfiguration>? tags,
     required Map<PlatformSelector, SuiteConfiguration>? onPlatform,
@@ -271,6 +279,7 @@
         _runSkipped = runSkipped,
         dart2jsArgs = _list(dart2jsArgs) ?? const [],
         _runtimes = _list(runtimes),
+        compilerSelections = _list(compilerSelections),
         tags = _map(tags),
         onPlatform = _map(onPlatform),
         _ignoreTimeouts = ignoreTimeouts,
@@ -293,6 +302,7 @@
         testSelections: const {},
         precompiledPath: null,
         runtimes: null,
+        compilerSelections: null,
         ignoreTimeouts: null,
       );
 
@@ -333,6 +343,7 @@
         testSelections:
             testSelections.isEmpty ? other.testSelections : testSelections,
         precompiledPath: other.precompiledPath ?? precompiledPath,
+        compilerSelections: other.compilerSelections ?? compilerSelections,
         runtimes: other._runtimes ?? _runtimes,
         tags: _mergeConfigMaps(tags, other.tags),
         onPlatform: _mergeConfigMaps(onPlatform, other.onPlatform),
@@ -352,6 +363,7 @@
       bool? runSkipped,
       Iterable<String>? dart2jsArgs,
       String? precompiledPath,
+      Iterable<CompilerSelection>? compilerSelections,
       Iterable<RuntimeSelection>? runtimes,
       Map<BooleanSelector, SuiteConfiguration>? tags,
       Map<PlatformSelector, SuiteConfiguration>? onPlatform,
@@ -376,6 +388,7 @@
         dart2jsArgs: dart2jsArgs?.toList() ?? this.dart2jsArgs,
         testSelections: testSelections,
         precompiledPath: precompiledPath ?? this.precompiledPath,
+        compilerSelections: compilerSelections ?? this.compilerSelections,
         runtimes: runtimes ?? _runtimes,
         tags: tags ?? this.tags,
         onPlatform: onPlatform ?? this.onPlatform,
@@ -410,6 +423,7 @@
         runSkipped: _runSkipped,
         dart2jsArgs: dart2jsArgs,
         precompiledPath: precompiledPath,
+        compilerSelections: compilerSelections,
         runtimes: _runtimes,
         tags: tags,
         onPlatform: onPlatform,
diff --git a/pkgs/test_core/lib/src/runner/vm/platform.dart b/pkgs/test_core/lib/src/runner/vm/platform.dart
index 2ea9483..2cb5a48 100644
--- a/pkgs/test_core/lib/src/runner/vm/platform.dart
+++ b/pkgs/test_core/lib/src/runner/vm/platform.dart
@@ -13,7 +13,7 @@
 import 'package:path/path.dart' as p;
 import 'package:stream_channel/isolate_channel.dart';
 import 'package:stream_channel/stream_channel.dart';
-import 'package:test_api/backend.dart'; // ignore: deprecated_member_use
+import 'package:test_api/backend.dart';
 import 'package:test_core/src/runner/vm/test_compiler.dart';
 import 'package:vm_service/vm_service.dart' hide Isolate;
 import 'package:vm_service/vm_service_io.dart';
@@ -23,9 +23,10 @@
 import '../../runner/load_exception.dart';
 import '../../runner/platform.dart';
 import '../../runner/plugin/platform_helpers.dart';
+import '../../runner/plugin/shared_platform_helpers.dart';
 import '../../runner/runner_suite.dart';
 import '../../runner/suite.dart';
-import '../../util/dart.dart' as dart;
+import '../../util/io.dart';
 import '../../util/package_config.dart';
 import '../package_version.dart';
 import 'environment.dart';
@@ -40,6 +41,7 @@
       p.join(p.current, '.dart_tool', 'test', 'incremental_kernel'));
   final _closeMemo = AsyncMemoizer<void>();
   final _workingDirectory = Directory.current.uri;
+  final _tempDir = Directory.systemTemp.createTempSync('dart_test.vm.');
 
   @override
   Future<RunnerSuite?> load(String path, SuitePlatform platform,
@@ -48,23 +50,48 @@
 
     _setupPauseAfterTests();
 
-    var receivePort = ReceivePort();
+    MultiChannel outerChannel;
+    var cleanupCallbacks = <void Function()>[];
     Isolate? isolate;
-    try {
-      isolate =
-          await _spawnIsolate(path, receivePort.sendPort, suiteConfig.metadata);
-      if (isolate == null) return null;
-    } catch (error) {
-      receivePort.close();
-      rethrow;
+    if (platform.compiler == Compiler.exe) {
+      var serverSocket = await ServerSocket.bind('localhost', 0);
+      Process process;
+      try {
+        process =
+            await _spawnExecutable(path, suiteConfig.metadata, serverSocket);
+      } catch (error) {
+        serverSocket.close();
+        rethrow;
+      }
+      process.stdout.listen(stdout.add);
+      process.stderr.listen(stderr.add);
+      var socket = await serverSocket.first;
+      outerChannel = MultiChannel<Object?>(jsonSocketStreamChannel(socket));
+      cleanupCallbacks
+        ..add(serverSocket.close)
+        ..add(process.kill);
+    } else {
+      var receivePort = ReceivePort();
+      try {
+        isolate = await _spawnIsolate(path, receivePort.sendPort,
+            suiteConfig.metadata, platform.compiler);
+        if (isolate == null) return null;
+      } catch (error) {
+        receivePort.close();
+        rethrow;
+      }
+      outerChannel = MultiChannel(IsolateChannel.connectReceive(receivePort));
+      cleanupCallbacks
+        ..add(receivePort.close)
+        ..add(isolate.kill);
     }
+    cleanupCallbacks.add(outerChannel.sink.close);
 
     VmService? client;
     StreamSubscription<Event>? eventSub;
     // Typical test interaction will go across `channel`, `outerChannel` adds
     // additional communication directly between the test bootstrapping and this
     // platform to enable pausing after tests for debugging.
-    var outerChannel = MultiChannel(IsolateChannel.connectReceive(receivePort));
     var outerQueue = StreamQueue(outerChannel.stream);
     var channelId = (await outerQueue.next) as int;
     var channel = outerChannel.virtualChannel(channelId).transformStream(
@@ -73,8 +100,9 @@
         outerChannel.sink.add('debug');
         await outerQueue.next;
       }
-      receivePort.close();
-      isolate!.kill();
+      for (var fn in cleanupCallbacks) {
+        fn();
+      }
       eventSub?.cancel();
       client?.dispose();
       sink.close();
@@ -83,9 +111,15 @@
     Environment? environment;
     IsolateRef? isolateRef;
     if (_config.debug) {
+      if (platform.compiler == Compiler.exe) {
+        throw UnsupportedError(
+            'Unable to debug tests compiled to `exe` (tried to debug $path with '
+            'the `exe` compiler).');
+      }
       var info =
           await Service.controlWebServer(enable: true, silenceOutput: true);
-      var isolateID = Service.getIsolateID(isolate)!;
+      // ignore: deprecated_member_use, Remove when SDK constraint is at 3.2.0
+      var isolateID = Service.getIsolateID(isolate!)!;
 
       var libraryPath = _absolute(path).toString();
       var serverUri = info.serverUri!;
@@ -125,7 +159,10 @@
   }
 
   @override
-  Future close() => _closeMemo.runOnce(_compiler.dispose);
+  Future close() => _closeMemo.runOnce(() => Future.wait([
+        _compiler.dispose(),
+        _tempDir.deleteWithRetry(),
+      ]));
 
   Uri _absolute(String path) {
     final uri = p.toUri(path);
@@ -133,63 +170,118 @@
     return _workingDirectory.resolveUri(uri);
   }
 
-  /// Spawns an isolate and passes it [message].
+  /// Compiles [path] to a native executable and spawns it as a process.
+  ///
+  /// Sets up a communication channel as well by passing command line arguments
+  /// for the host and port of [socket].
+  Future<Process> _spawnExecutable(
+      String path, Metadata suiteMetadata, ServerSocket socket) async {
+    if (_config.suiteDefaults.precompiledPath != null) {
+      throw UnsupportedError(
+          'Precompiled native executable tests are not supported at this time');
+    }
+    var executable = await _compileToNative(path, suiteMetadata);
+    return await Process.start(
+        executable, [socket.address.host, socket.port.toString()]);
+  }
+
+  /// Compiles [path] to a native executable using `dart compile exe`.
+  Future<String> _compileToNative(String path, Metadata suiteMetadata) async {
+    var bootstrapPath = _bootstrapNativeTestFile(
+        path,
+        suiteMetadata.languageVersionComment ??
+            await rootPackageLanguageVersionComment);
+    var output = File(p.setExtension(bootstrapPath, '.exe'));
+    var processResult = await Process.run(Platform.resolvedExecutable, [
+      'compile',
+      'exe',
+      bootstrapPath,
+      '--output',
+      output.path,
+      '--packages',
+      (await packageConfigUri).toFilePath(),
+    ]);
+    if (processResult.exitCode != 0 || !(await output.exists())) {
+      throw LoadException(path, '''
+exitCode: ${processResult.exitCode}
+stdout: ${processResult.stdout}
+stderr: ${processResult.stderr}''');
+    }
+    return output.path;
+  }
+
+  /// Spawns an isolate with the current configuration and passes it [message].
   ///
   /// This isolate connects an [IsolateChannel] to [message] and sends the
   /// serialized tests over that channel.
-  Future<Isolate?> _spawnIsolate(
-      String path, SendPort message, Metadata suiteMetadata) async {
+  ///
+  /// Returns `null` if an exception occurs but [close] has already been called.
+  Future<Isolate?> _spawnIsolate(String path, SendPort message,
+      Metadata suiteMetadata, Compiler compiler) async {
     try {
       var precompiledPath = _config.suiteDefaults.precompiledPath;
       if (precompiledPath != null) {
-        return _spawnPrecompiledIsolate(path, message, precompiledPath);
+        return _spawnPrecompiledIsolate(
+            path, message, precompiledPath, compiler);
       } else if (_config.pubServeUrl != null) {
-        return _spawnPubServeIsolate(path, message, _config.pubServeUrl!);
-      } else if (_config.useDataIsolateStrategy) {
-        return _spawnDataIsolate(path, message, suiteMetadata);
-      } else {
-        return _spawnKernelIsolate(path, message, suiteMetadata);
+        return _spawnPubServeIsolate(
+            path, message, _config.pubServeUrl!, compiler);
       }
+      return switch (compiler) {
+        Compiler.kernel => _spawnIsolateWithUri(
+            await _compileToKernel(path, suiteMetadata), message),
+        Compiler.source => _spawnIsolateWithUri(
+            _bootstrapIsolateTestFile(
+                path,
+                suiteMetadata.languageVersionComment ??
+                    await rootPackageLanguageVersionComment),
+            message),
+        _ => throw StateError(
+            'Unsupported compiler $compiler for the VM platform'),
+      };
     } catch (_) {
       if (_closeMemo.hasRun) return null;
       rethrow;
     }
   }
 
-  /// Compiles [path] to kernel using [_compiler] and spawns that in an
-  /// isolate.
-  Future<Isolate> _spawnKernelIsolate(
-      String path, SendPort message, Metadata suiteMetadata) async {
+  /// Compiles [path] to kernel and returns the uri to the compiled dill.
+  Future<Uri> _compileToKernel(String path, Metadata suiteMetadata) async {
     final response = await _compiler.compile(_absolute(path), suiteMetadata);
     var compiledDill = response.kernelOutputUri?.toFilePath();
     if (compiledDill == null || response.errorCount > 0) {
       throw LoadException(path, response.compilerOutput ?? 'unknown error');
     }
-    return await Isolate.spawnUri(p.toUri(compiledDill), [], message,
+    return _absolute(compiledDill);
+  }
+
+  /// Runs [uri] in an isolate, passing [message].
+  Future<Isolate> _spawnIsolateWithUri(Uri uri, SendPort message) async {
+    return await Isolate.spawnUri(uri, [], message,
         packageConfig: await packageConfigUri, checked: true);
   }
 
-  Future<Isolate> _spawnDataIsolate(
-      String path, SendPort message, Metadata suiteMetadata) async {
-    return await dart.runInIsolate('''
-    ${suiteMetadata.languageVersionComment ?? await rootPackageLanguageVersionComment}
-    import "dart:isolate";
-    import "package:test_core/src/bootstrap/vm.dart";
-    import "${_absolute(path)}" as test;
-    void main(_, SendPort sendPort) {
-      internalBootstrapVmTest(() => test.main, sendPort);
-    }
-  ''', message);
-  }
-
-  Future<Isolate> _spawnPrecompiledIsolate(
-      String testPath, SendPort message, String precompiledPath) async {
+  Future<Isolate> _spawnPrecompiledIsolate(String testPath, SendPort message,
+      String precompiledPath, Compiler compiler) async {
     testPath =
         _absolute('${p.join(precompiledPath, testPath)}.vm_test.dart').path;
-    var dillTestpath =
-        '${testPath.substring(0, testPath.length - '.dart'.length)}.vm.app.dill';
-    if (await File(dillTestpath).exists()) {
-      testPath = dillTestpath;
+    switch (compiler) {
+      case Compiler.kernel:
+        var dillTestpath =
+            '${testPath.substring(0, testPath.length - '.dart'.length)}'
+            '.vm.app.dill';
+        if (await File(dillTestpath).exists()) {
+          testPath = dillTestpath;
+        }
+        // TODO: Compile to kernel manually here? Otherwise we aren't compiling
+        // with kernel when we technically should be, based on the compiler
+        // setting.
+        break;
+      case Compiler.source:
+        // Just leave test path as is.
+        break;
+      default:
+        throw StateError('Unsupported compiler for the VM platform $compiler.');
     }
     File? packageConfig =
         File(p.join(precompiledPath, '.dart_tool/package_config.json'));
@@ -202,8 +294,69 @@
     return await Isolate.spawnUri(p.toUri(testPath), [], message,
         packageConfig: packageConfig?.uri, checked: true);
   }
+
+  /// Bootstraps the test at [testPath] and writes its contents to a temporary
+  /// file.
+  ///
+  /// Returns the [Uri] to the created file.
+  Uri _bootstrapIsolateTestFile(
+      String testPath, String languageVersionComment) {
+    var file = File(p.join(
+        _tempDir.path, p.setExtension(testPath, '.bootstrap.isolate.dart')));
+    if (!file.existsSync()) {
+      file
+        ..createSync(recursive: true)
+        ..writeAsStringSync(_bootstrapIsolateTestContents(
+            _absolute(testPath), languageVersionComment));
+    }
+    return file.uri;
+  }
+
+  /// Bootstraps the test at [testPath] for native execution and writes its
+  /// contents to a temporary file.
+  ///
+  /// Returns the path to the created file.
+  String _bootstrapNativeTestFile(
+      String testPath, String languageVersionComment) {
+    var file = File(p.join(
+        _tempDir.path, p.setExtension(testPath, '.bootstrap.native.dart')));
+    if (!file.existsSync()) {
+      file
+        ..createSync(recursive: true)
+        ..writeAsStringSync(_bootstrapNativeTestContents(
+            _absolute(testPath), languageVersionComment));
+    }
+    return file.path;
+  }
 }
 
+/// Creates bootstrap file contents for running [testUri] in a VM isolate.
+String _bootstrapIsolateTestContents(
+        Uri testUri, String languageVersionComment) =>
+    '''
+    $languageVersionComment
+    import "dart:isolate";
+    import "package:test_core/src/bootstrap/vm.dart";
+    import "$testUri" as test;
+    void main(_, SendPort sendPort) {
+      internalBootstrapVmTest(() => test.main, sendPort);
+    }
+  ''';
+
+/// Creates bootstrap file contents for running [testUri] as a native
+/// executable.
+String _bootstrapNativeTestContents(
+        Uri testUri, String languageVersionComment) =>
+    '''
+    $languageVersionComment
+    import "dart:isolate";
+    import "package:test_core/src/bootstrap/vm.dart";
+    import "$testUri" as test;
+    void main(List<String> args) {
+      internalBootstrapNativeTest(() => test.main, args);
+    }
+  ''';
+
 Future<Map<String, dynamic>> _gatherCoverage(Environment environment) async {
   final isolateId = Uri.parse(environment.observatoryUrl!.fragment)
       .queryParameters['isolateId'];
@@ -211,8 +364,13 @@
       isolateIds: {isolateId!});
 }
 
-Future<Isolate> _spawnPubServeIsolate(
-    String testPath, SendPort message, Uri pubServeUrl) async {
+Future<Isolate> _spawnPubServeIsolate(String testPath, SendPort message,
+    Uri pubServeUrl, Compiler compiler) async {
+  if (compiler != Compiler.source) {
+    throw ArgumentError(
+        'The --pub-serve option requires the `--compiler none` option but the '
+        'compiler was $compiler');
+  }
   var url = pubServeUrl.resolveUri(
       p.toUri('${p.relative(testPath, from: 'test')}.vm_test.dart'));
 
diff --git a/pkgs/test_core/lib/src/runner/vm/test_compiler.dart b/pkgs/test_core/lib/src/runner/vm/test_compiler.dart
index 9533473..ba3c4b7 100644
--- a/pkgs/test_core/lib/src/runner/vm/test_compiler.dart
+++ b/pkgs/test_core/lib/src/runner/vm/test_compiler.dart
@@ -10,9 +10,10 @@
 import 'package:frontend_server_client/frontend_server_client.dart';
 import 'package:path/path.dart' as p;
 import 'package:pool/pool.dart';
-import 'package:test_api/backend.dart'; // ignore: deprecated_member_use
+import 'package:test_api/backend.dart';
 
 import '../../util/dart.dart';
+import '../../util/io.dart';
 import '../../util/package_config.dart';
 import '../package_version.dart';
 
@@ -72,7 +73,7 @@
   late final _outputDill =
       File(p.join(_outputDillDirectory.path, 'output.dill'));
   final _outputDillDirectory =
-      Directory.systemTemp.createTempSync('dart_test.');
+      Directory.systemTemp.createTempSync('dart_test.kernel.');
   // Used to create unique file names for final kernel files.
   int _compileNumber = 0;
   // The largest incremental dill file we created, will be cached under
@@ -158,13 +159,25 @@
     final platformDill = 'lib/_internal/vm_platform_strong.dill';
     final sdkRoot =
         p.relative(p.dirname(p.dirname(Platform.resolvedExecutable)));
+    final packageConfigUriAwaited = await packageConfigUri;
+
+    // If we have native assets for the host os in JIT mode, they are here.
+    Uri? nativeAssetsYaml;
+    if (enabledExperiments.contains('native-assets')) {
+      nativeAssetsYaml = packageConfigUriAwaited.resolve('native_assets.yaml');
+      if (!await File.fromUri(nativeAssetsYaml).exists()) {
+        nativeAssetsYaml = null;
+      }
+    }
+
     var client = _frontendServerClient = await FrontendServerClient.start(
       testUri.toString(),
       _outputDill.path,
       platformDill,
       enabledExperiments: enabledExperiments,
       sdkRoot: sdkRoot,
-      packagesJson: (await packageConfigUri).toFilePath(),
+      packagesJson: packageConfigUriAwaited.toFilePath(),
+      nativeAssets: nativeAssetsYaml?.toFilePath(),
       printIncrementalDependencies: false,
     );
     return client.compile();
@@ -182,7 +195,7 @@
         _frontendServerClient?.kill();
         _frontendServerClient = null;
         if (_outputDillDirectory.existsSync()) {
-          _outputDillDirectory.deleteSync(recursive: true);
+          await _outputDillDirectory.deleteWithRetry();
         }
       });
 }
diff --git a/pkgs/test_core/lib/src/util/errors.dart b/pkgs/test_core/lib/src/util/errors.dart
index d528cac..7ebea6e 100644
--- a/pkgs/test_core/lib/src/util/errors.dart
+++ b/pkgs/test_core/lib/src/util/errors.dart
@@ -10,5 +10,5 @@
 ///
 /// Many exceptions include the exception class name at the beginning of their
 /// [toString], so we remove that if it exists.
-String getErrorMessage(error) =>
+String getErrorMessage(Object error) =>
     error.toString().replaceFirst(_exceptionPrefix, '');
diff --git a/pkgs/test_core/lib/src/util/io.dart b/pkgs/test_core/lib/src/util/io.dart
index da9f072..59e613c 100644
--- a/pkgs/test_core/lib/src/util/io.dart
+++ b/pkgs/test_core/lib/src/util/io.dart
@@ -7,9 +7,11 @@
 import 'dart:core' as core;
 import 'dart:core';
 import 'dart:io';
+import 'dart:math';
 
 import 'package:async/async.dart';
 import 'package:path/path.dart' as p;
+import 'package:test_api/src/backend/compiler.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/operating_system.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/suite_platform.dart'; // ignore: implementation_imports
@@ -46,9 +48,11 @@
 /// [inGoogle] determined automatically.
 ///
 /// If [runtime] is a browser, this will set [os] to [OperatingSystem.none].
-SuitePlatform currentPlatform(Runtime runtime) => SuitePlatform(runtime,
-    os: runtime.isBrowser ? OperatingSystem.none : currentOS,
-    inGoogle: inGoogle);
+SuitePlatform currentPlatform(Runtime runtime, Compiler? compiler) =>
+    SuitePlatform(runtime,
+        compiler: compiler,
+        os: runtime.isBrowser ? OperatingSystem.none : currentOS,
+        inGoogle: inGoogle);
 
 /// A transformer that decodes bytes using UTF-8 and splits them on newlines.
 final lineSplitter = StreamTransformer<List<int>, String>(
@@ -109,7 +113,7 @@
   return Future.sync(() {
     var tempDir = createTempDir();
     return Future.sync(() => fn(tempDir))
-        .whenComplete(() => Directory(tempDir).deleteSync(recursive: true));
+        .whenComplete(() => Directory(tempDir).deleteWithRetry());
   });
 }
 
@@ -223,3 +227,19 @@
     return base;
   }
 }
+
+extension RetryDelete on FileSystemEntity {
+  Future<void> deleteWithRetry() async {
+    var attempt = 0;
+    while (true) {
+      try {
+        await delete(recursive: true);
+        return;
+      } on FileSystemException {
+        if (attempt == 2) rethrow;
+        attempt++;
+        await Future.delayed(Duration(milliseconds: pow(10, attempt).toInt()));
+      }
+    }
+  }
+}
diff --git a/pkgs/test_core/lib/src/util/io_stub.dart b/pkgs/test_core/lib/src/util/io_stub.dart
index eee35d4..7953877 100644
--- a/pkgs/test_core/lib/src/util/io_stub.dart
+++ b/pkgs/test_core/lib/src/util/io_stub.dart
@@ -2,8 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:test_api/src/backend/compiler.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
 import 'package:test_api/src/backend/suite_platform.dart'; // ignore: implementation_imports
 
-SuitePlatform currentPlatform(Runtime runtime) => throw UnsupportedError(
-    'Getting the current platform is only supported where dart:io exists');
+SuitePlatform currentPlatform(Runtime runtime, Compiler? compiler) =>
+    throw UnsupportedError(
+        'Getting the current platform is only supported where dart:io exists');
diff --git a/pkgs/test_core/lib/src/util/pair.dart b/pkgs/test_core/lib/src/util/pair.dart
index 61dcff7..89a3d14 100644
--- a/pkgs/test_core/lib/src/util/pair.dart
+++ b/pkgs/test_core/lib/src/util/pair.dart
@@ -13,7 +13,7 @@
   String toString() => '($first, $last)';
 
   @override
-  bool operator ==(other) {
+  bool operator ==(Object other) {
     if (other is! Pair) return false;
     return other.first == first && other.last == last;
   }
diff --git a/pkgs/test_core/lib/src/util/stack_trace_mapper.dart b/pkgs/test_core/lib/src/util/stack_trace_mapper.dart
index 9e8650a..9d4248d 100644
--- a/pkgs/test_core/lib/src/util/stack_trace_mapper.dart
+++ b/pkgs/test_core/lib/src/util/stack_trace_mapper.dart
@@ -4,11 +4,10 @@
 
 import 'package:source_map_stack_trace/source_map_stack_trace.dart' as mapper;
 import 'package:source_maps/source_maps.dart';
-// ignore: deprecated_member_use
 import 'package:test_api/backend.dart' show StackTraceMapper;
 
 /// A class for mapping JS stack traces to Dart stack traces using source maps.
-class JSStackTraceMapper extends StackTraceMapper {
+class JSStackTraceMapper implements StackTraceMapper {
   /// The parsed source map.
   ///
   /// This is initialized lazily in `mapStackTrace()`.
diff --git a/pkgs/test_core/lib/src/util/string_literal_iterator.dart b/pkgs/test_core/lib/src/util/string_literal_iterator.dart
index 2a8b118..d58f64a 100644
--- a/pkgs/test_core/lib/src/util/string_literal_iterator.dart
+++ b/pkgs/test_core/lib/src/util/string_literal_iterator.dart
@@ -36,7 +36,7 @@
 ///
 /// In addition to exposing the values of the runes themselves, this also
 /// exposes the offset of the current rune in the Dart source file.
-class StringLiteralIterator extends Iterator<int> {
+class StringLiteralIterator implements Iterator<int> {
   @override
   int get current => _current!;
   int? _current;
diff --git a/pkgs/test_core/lib/test_core.dart b/pkgs/test_core/lib/test_core.dart
index c603586..01f4454 100644
--- a/pkgs/test_core/lib/test_core.dart
+++ b/pkgs/test_core/lib/test_core.dart
@@ -6,12 +6,6 @@
     'Please use package:test.')
 library test_core;
 
-export 'package:test_api/expect.dart';
 export 'package:test_api/hooks.dart' show TestFailure;
-// Not yet deprecated, but not exposed through focused libraries.
-export 'package:test_api/test_api.dart' show registerException;
-// Deprecated exports not surfaced through focused libraries.
-export 'package:test_api/test_api.dart'
-    show ErrorFormatter, expectAsync, throws, Throws;
 
 export 'scaffolding.dart';
diff --git a/pkgs/test_core/pubspec.yaml b/pkgs/test_core/pubspec.yaml
index 1244a99..afffdcb 100644
--- a/pkgs/test_core/pubspec.yaml
+++ b/pkgs/test_core/pubspec.yaml
@@ -1,19 +1,19 @@
 name: test_core
-version: 0.4.23-dev
+version: 0.5.7-wip
 description: A basic library for writing tests and running them on the VM.
 repository: https://github.com/dart-lang/test/tree/master/pkgs/test_core
 
 environment:
- sdk: '>=2.18.0 <3.0.0'
+  sdk: ^3.0.0
 
 dependencies:
-  analyzer: '>=3.3.0 <6.0.0'
-  async: ^2.5.0
+  analyzer: '>=3.3.0 <7.0.0'
   args: ^2.0.0
+  async: ^2.5.0
   boolean_selector: ^2.1.0
   collection: ^1.15.0
   coverage: ^1.0.0
-  frontend_server_client: '>=2.1.0 <4.0.0'
+  frontend_server_client: '>=3.2.0 <4.0.0'
   glob: ^2.0.0
   io: ^1.0.0
   meta: ^1.3.0
@@ -25,12 +25,10 @@
   source_span: ^1.8.0
   stack_trace: ^1.10.0
   stream_channel: ^2.1.0
-  vm_service: ">=6.0.0 <11.0.0"
-  yaml: ^3.0.0
-  # matcher is tightly constrained by test_api
-  matcher: any
   # Use an exact version until the test_api package is stable.
-  test_api: 0.4.18
+  test_api: 0.6.1
+  vm_service: ">=6.0.0 <12.0.0"
+  yaml: ^3.0.0
 
 dev_dependencies:
-  lints: '>=1.0.0 <3.0.0'
+  dart_flutter_team_lints: ^1.0.0
diff --git a/tool/ci.sh b/tool/ci.sh
index e8dec9f..a16044e 100755
--- a/tool/ci.sh
+++ b/tool/ci.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Created with package:mono_repo v6.5.0
+# Created with package:mono_repo v6.5.7
 
 # Support built in commands on windows out of the box.
 # When it is a flutter repo (check the pubspec.yaml for "sdk: flutter")
@@ -76,50 +76,54 @@
         dart analyze || EXIT_CODE=$?
         ;;
       command_00)
+        echo 'pushd /tmp && wget https://dl.google.com/linux/direct/google-chrome-beta_current_amd64.deb && sudo dpkg -i google-chrome-beta_current_amd64.deb && popd && which google-chrome-beta'
+        pushd /tmp && wget https://dl.google.com/linux/direct/google-chrome-beta_current_amd64.deb && sudo dpkg -i google-chrome-beta_current_amd64.deb && popd && which google-chrome-beta || EXIT_CODE=$?
+        ;;
+      command_01)
         echo 'dart test'
         dart test || EXIT_CODE=$?
         ;;
-      command_01)
+      command_02)
         echo 'xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 0'
         xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 0 || EXIT_CODE=$?
         ;;
-      command_02)
+      command_03)
         echo 'xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 1'
         xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 1 || EXIT_CODE=$?
         ;;
-      command_03)
+      command_04)
         echo 'xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 2'
         xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 2 || EXIT_CODE=$?
         ;;
-      command_04)
+      command_05)
         echo 'xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 3'
         xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 3 || EXIT_CODE=$?
         ;;
-      command_05)
+      command_06)
         echo 'xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 4'
         xvfb-run -s "-screen 0 1024x768x24" dart test --preset travis --total-shards 5 --shard-index 4 || EXIT_CODE=$?
         ;;
-      command_06)
+      command_07)
         echo 'dart test --preset travis --total-shards 5 --shard-index 0'
         dart test --preset travis --total-shards 5 --shard-index 0 || EXIT_CODE=$?
         ;;
-      command_07)
+      command_08)
         echo 'dart test --preset travis --total-shards 5 --shard-index 1'
         dart test --preset travis --total-shards 5 --shard-index 1 || EXIT_CODE=$?
         ;;
-      command_08)
+      command_09)
         echo 'dart test --preset travis --total-shards 5 --shard-index 2'
         dart test --preset travis --total-shards 5 --shard-index 2 || EXIT_CODE=$?
         ;;
-      command_09)
+      command_10)
         echo 'dart test --preset travis --total-shards 5 --shard-index 3'
         dart test --preset travis --total-shards 5 --shard-index 3 || EXIT_CODE=$?
         ;;
-      command_10)
+      command_11)
         echo 'dart test --preset travis --total-shards 5 --shard-index 4'
         dart test --preset travis --total-shards 5 --shard-index 4 || EXIT_CODE=$?
         ;;
-      command_11)
+      command_12)
         echo 'dart test --preset travis -x browser'
         dart test --preset travis -x browser || EXIT_CODE=$?
         ;;
@@ -127,10 +131,14 @@
         echo 'dart format --output=none --set-exit-if-changed .'
         dart format --output=none --set-exit-if-changed . || EXIT_CODE=$?
         ;;
-      test)
+      test_0)
         echo 'dart test -p chrome,vm,node'
         dart test -p chrome,vm,node || EXIT_CODE=$?
         ;;
+      test_1)
+        echo 'dart test --timeout=60s'
+        dart test --timeout=60s || EXIT_CODE=$?
+        ;;
       *)
         echo -e "\033[31mUnknown TASK '${TASK}' - TERMINATING JOB\033[0m"
         exit 64