diff --git a/.github/workflows/changelog_reminder.yml b/.github/workflows/changelog_reminder.yml index f5a0eddacc..0544d21bcb 100644 --- a/.github/workflows/changelog_reminder.yml +++ b/.github/workflows/changelog_reminder.yml @@ -13,9 +13,13 @@ jobs: if: ${{ !contains(github.event.*.labels.*.name, 'changelog-not-required') }} name: Maybe prevent submission runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - name: Check changed files run: | git fetch origin main diff --git a/.github/workflows/daily_stable_testing.yml b/.github/workflows/daily_stable_testing.yml index 9f6d407eae..72c9b4c58e 100644 --- a/.github/workflows/daily_stable_testing.yml +++ b/.github/workflows/daily_stable_testing.yml @@ -16,6 +16,8 @@ jobs: testing_stable: name: Testing Dart Stable SDK runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Set up stable Dart SDK uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c @@ -31,6 +33,7 @@ jobs: id: checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: + persist-credentials: false ref: webdev-v${{ steps.version.outputs.VERSION_TAG }} - name: Upgrade deps id: webdev_pub_upgrade diff --git a/.github/workflows/daily_testing.yml b/.github/workflows/daily_testing.yml index 7d314a705d..e0902839a8 100644 --- a/.github/workflows/daily_testing.yml +++ b/.github/workflows/daily_testing.yml @@ -10,6 +10,8 @@ jobs: daily_testing: name: Daily Testing runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Setup Dart SDK uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c @@ -18,6 +20,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 0f43dd4a15..10a09b67f6 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -1,4 +1,4 @@ -# Created with package:mono_repo v6.6.3 +# Created with package:mono_repo v6.7.2 name: Dart CI on: push: @@ -14,7 +14,8 @@ defaults: env: PUB_ENVIRONMENT: bot.github DISPLAY: ":99" -permissions: read-all +permissions: + contents: read jobs: job_001: @@ -36,8 +37,10 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - name: mono_repo self validate - run: dart pub global activate mono_repo 6.6.3 + run: dart pub global activate mono_repo 6.7.2 - name: mono_repo self validate run: dart pub global run mono_repo generate --validate job_002: @@ -61,6 +64,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade @@ -99,6 +104,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_test_common_pub_upgrade name: dwds_test_common; dart pub upgrade run: dart pub upgrade @@ -172,6 +179,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: webdev_pub_upgrade name: webdev; dart pub upgrade run: dart pub upgrade @@ -190,14 +199,14 @@ jobs: if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'" working-directory: webdev job_005: - name: "unit_test; linux; Dart dev; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test --tags=extension`" + name: "unit_test; linux; Dart dev; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV`, `dart test --tags=extension`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:command-test_1" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:command_0-command_1-test_1" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds os:ubuntu-latest;pub-cache-hosted;sdk:dev @@ -210,6 +219,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade @@ -219,6 +230,10 @@ jobs: run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" working-directory: dwds + - name: "dwds; echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + run: "echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" + working-directory: dwds - name: "dwds; dart test --tags=extension" run: "dart test --tags=extension" if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" @@ -229,14 +244,14 @@ jobs: - job_003 - job_004 job_006: - name: "unit_test; linux; Dart dev; PKG: dwds; `dart test --total-shards 3 --shard-index 0 --exclude-tags=extension`" + name: "unit_test; linux; Dart dev; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV`, `dart test --total-shards 3 --shard-index 0 --exclude-tags=extension`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:test_2" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:command_0-command_1-test_2" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds os:ubuntu-latest;pub-cache-hosted;sdk:dev @@ -249,11 +264,21 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" working-directory: dwds + - name: "dwds; Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" + run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" + if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" + working-directory: dwds + - name: "dwds; echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + run: "echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" + working-directory: dwds - name: "dwds; dart test --total-shards 3 --shard-index 0 --exclude-tags=extension" run: "dart test --total-shards 3 --shard-index 0 --exclude-tags=extension" if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" @@ -264,14 +289,14 @@ jobs: - job_003 - job_004 job_007: - name: "unit_test; linux; Dart dev; PKG: dwds; `dart test --total-shards 3 --shard-index 1 --exclude-tags=extension`" + name: "unit_test; linux; Dart dev; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV`, `dart test --total-shards 3 --shard-index 1 --exclude-tags=extension`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:test_3" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:command_0-command_1-test_3" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds os:ubuntu-latest;pub-cache-hosted;sdk:dev @@ -284,11 +309,21 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" working-directory: dwds + - name: "dwds; Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" + run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" + if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" + working-directory: dwds + - name: "dwds; echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + run: "echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" + working-directory: dwds - name: "dwds; dart test --total-shards 3 --shard-index 1 --exclude-tags=extension" run: "dart test --total-shards 3 --shard-index 1 --exclude-tags=extension" if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" @@ -299,14 +334,14 @@ jobs: - job_003 - job_004 job_008: - name: "unit_test; linux; Dart dev; PKG: dwds; `dart test --total-shards 3 --shard-index 2 --exclude-tags=extension`" + name: "unit_test; linux; Dart dev; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV`, `dart test --total-shards 3 --shard-index 2 --exclude-tags=extension`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:test_4" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds;commands:command_0-command_1-test_4" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds os:ubuntu-latest;pub-cache-hosted;sdk:dev @@ -319,11 +354,21 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" working-directory: dwds + - name: "dwds; Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" + run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" + if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" + working-directory: dwds + - name: "dwds; echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + run: "echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" + working-directory: dwds - name: "dwds; dart test --total-shards 3 --shard-index 2 --exclude-tags=extension" run: "dart test --total-shards 3 --shard-index 2 --exclude-tags=extension" if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" @@ -334,14 +379,14 @@ jobs: - job_003 - job_004 job_009: - name: "unit_test; linux; Dart dev; PKG: dwds_test_common; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test --exclude-tags=release`" + name: "unit_test; linux; Dart dev; PKG: dwds_test_common; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV`, `dart test --exclude-tags=release`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds_test_common;commands:command-test_6" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds_test_common;commands:command_0-command_1-test_6" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:dwds_test_common os:ubuntu-latest;pub-cache-hosted;sdk:dev @@ -354,6 +399,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_test_common_pub_upgrade name: dwds_test_common; dart pub upgrade run: dart pub upgrade @@ -363,6 +410,10 @@ jobs: run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" if: "always() && steps.dwds_test_common_pub_upgrade.conclusion == 'success'" working-directory: dwds_test_common + - name: "dwds_test_common; echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + run: "echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + if: "always() && steps.dwds_test_common_pub_upgrade.conclusion == 'success'" + working-directory: dwds_test_common - name: "dwds_test_common; dart test --exclude-tags=release" run: "dart test --exclude-tags=release" if: "always() && steps.dwds_test_common_pub_upgrade.conclusion == 'success'" @@ -393,6 +444,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: frontend_server_client_pub_upgrade name: frontend_server_client; dart pub upgrade run: dart pub upgrade @@ -408,14 +461,14 @@ jobs: - job_003 - job_004 job_011: - name: "unit_test; linux; Dart dev; PKG: webdev; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test -j 1`" + name: "unit_test; linux; Dart dev; PKG: webdev; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV`, `dart test -j 1`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:webdev;commands:command-test_5" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:webdev;commands:command_0-command_1-test_5" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:webdev os:ubuntu-latest;pub-cache-hosted;sdk:dev @@ -428,6 +481,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: webdev_pub_upgrade name: webdev; dart pub upgrade run: dart pub upgrade @@ -437,6 +492,10 @@ jobs: run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'" working-directory: webdev + - name: "webdev; echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + run: "echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'" + working-directory: webdev - name: "webdev; dart test -j 1" run: dart test -j 1 if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'" @@ -457,6 +516,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade @@ -482,6 +543,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade @@ -507,6 +570,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade @@ -532,6 +597,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade @@ -557,6 +624,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_test_common_pub_upgrade name: dwds_test_common; dart pub upgrade run: dart pub upgrade @@ -582,6 +651,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: frontend_server_client_pub_upgrade name: frontend_server_client; dart pub upgrade run: dart pub upgrade @@ -607,6 +678,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: webdev_pub_upgrade name: webdev; dart pub upgrade run: dart pub upgrade @@ -622,7 +695,7 @@ jobs: - job_003 - job_004 job_019: - name: "beta_cron; linux; Dart beta; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test -j 1`" + name: "beta_cron; linux; Dart beta; PKG: dwds; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV`, `dart test -j 1`" runs-on: ubuntu-latest if: "github.event_name == 'schedule'" steps: @@ -630,7 +703,7 @@ jobs: uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:dwds;commands:command-test_5" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:dwds;commands:command_0-command_1-test_5" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:dwds os:ubuntu-latest;pub-cache-hosted;sdk:beta @@ -643,6 +716,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade @@ -652,6 +727,10 @@ jobs: run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" working-directory: dwds + - name: "dwds; echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + run: "echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" + working-directory: dwds - name: "dwds; dart test -j 1" run: dart test -j 1 if: "always() && steps.dwds_pub_upgrade.conclusion == 'success'" @@ -676,7 +755,7 @@ jobs: - job_017 - job_018 job_020: - name: "beta_cron; linux; Dart beta; PKG: webdev; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `dart test -j 1`" + name: "beta_cron; linux; Dart beta; PKG: webdev; `Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &`, `echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV`, `dart test -j 1`" runs-on: ubuntu-latest if: "github.event_name == 'schedule'" steps: @@ -684,7 +763,7 @@ jobs: uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:webdev;commands:command-test_5" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:webdev;commands:command_0-command_1-test_5" restore-keys: | os:ubuntu-latest;pub-cache-hosted;sdk:beta;packages:webdev os:ubuntu-latest;pub-cache-hosted;sdk:beta @@ -697,6 +776,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: webdev_pub_upgrade name: webdev; dart pub upgrade run: dart pub upgrade @@ -706,6 +787,10 @@ jobs: run: "Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &" if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'" working-directory: webdev + - name: "webdev; echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + run: "echo \"CHROME_EXECUTABLE=$(which google-chrome)\" >> $GITHUB_ENV" + if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'" + working-directory: webdev - name: "webdev; dart test -j 1" run: dart test -j 1 if: "always() && steps.webdev_pub_upgrade.conclusion == 'success'" @@ -751,6 +836,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade @@ -801,6 +888,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: webdev_pub_upgrade name: webdev; dart pub upgrade run: dart pub upgrade @@ -841,6 +930,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: dwds_pub_upgrade name: dwds; dart pub upgrade run: dart pub upgrade @@ -881,6 +972,8 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - id: webdev_pub_upgrade name: webdev; dart pub upgrade run: dart pub upgrade diff --git a/.github/workflows/dcm.yml b/.github/workflows/dcm.yml index 0ff2405f1b..c11fcf861e 100644 --- a/.github/workflows/dcm.yml +++ b/.github/workflows/dcm.yml @@ -12,6 +12,8 @@ jobs: dcm: name: Dart Code Metrics runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Install DCM run: | @@ -29,6 +31,7 @@ jobs: name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: + persist-credentials: false ref: "${{ github.event.pull_request.head.sha }}" - id: dwds_pub_upgrade name: dwds; dart pub upgrade diff --git a/.github/workflows/do_not_submit.yml b/.github/workflows/do_not_submit.yml index 2769dea9f3..d3141e1499 100644 --- a/.github/workflows/do_not_submit.yml +++ b/.github/workflows/do_not_submit.yml @@ -11,6 +11,7 @@ jobs: if: ${{ contains(github.event.*.labels.*.name, 'do-not-submit') }} name: Prevent submission runs-on: ubuntu-latest + permissions: {} steps: - name: Check for do-not-submit label run: | diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 0966f0687c..57944e2559 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -12,7 +12,7 @@ on: jobs: publish: if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@ed9c592c1d35106c0a8a52044426515017a60646 with: sdk: dev permissions: diff --git a/.github/workflows/pull_request_label.yml b/.github/workflows/pull_request_label.yml index 3115ed4548..d90d5f8dde 100644 --- a/.github/workflows/pull_request_label.yml +++ b/.github/workflows/pull_request_label.yml @@ -5,7 +5,8 @@ # https://github.com/actions/labeler. name: Pull Request Labeler -permissions: read-all +permissions: + contents: read on: pull_request_target diff --git a/.github/workflows/release_reminder.yml b/.github/workflows/release_reminder.yml index 56c85ec14d..3e0dd263ab 100644 --- a/.github/workflows/release_reminder.yml +++ b/.github/workflows/release_reminder.yml @@ -11,6 +11,8 @@ jobs: if: ${{ !contains(github.event.*.labels.*.name, 'prepare-release') }} name: Maybe prevent submission runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Setup Dart SDK uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c @@ -18,4 +20,6 @@ jobs: sdk: dev - id: checkout name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd \ No newline at end of file + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false \ No newline at end of file diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index a91b7be58a..703409e3bd 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -1,3 +1,7 @@ +## 27.1.3-wip + +- Internal test infrastructure refactoring: Move common test files to `dwds_test_common`. + ## 27.1.2 - Bump the min sdk to 3.13.0-107.0.dev. diff --git a/dwds/lib/src/handlers/injected_client_js.dart b/dwds/lib/src/handlers/injected_client_js.dart index 78ae20d65d..7c5ef69609 100644 --- a/dwds/lib/src/handlers/injected_client_js.dart +++ b/dwds/lib/src/handlers/injected_client_js.dart @@ -2,7 +2,7 @@ // Emits the transpiled client.js directly into a statically embeddable string. // dart format off -const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-values), the Dart to JavaScript compiler version: 3.13.0-107.0.dev.\n" +const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-values), the Dart to JavaScript compiler version: 3.14.0-edge.49708da8bbb61fcaf57229ecfad88ee2db967f44.\n" "// The code supports the following hooks:\n" "// dartPrint(message):\n" "// if this function is defined it is called instead of the Dart [print]\n" @@ -235,6 +235,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " },\n" " getNativeInterceptor(object) {\n" " var proto, objectProto, \$constructor, interceptor, t1,\n" +" _s9_ = \"_\$dart_js\",\n" " record = object[init.dispatchPropertyName];\n" " if (record == null)\n" " if (\$.initNativeDispatchFlag == null) {\n" @@ -259,7 +260,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " else {\n" " t1 = \$._JS_INTEROP_INTERCEPTOR_TAG;\n" " if (t1 == null)\n" -" t1 = \$._JS_INTEROP_INTERCEPTOR_TAG = init.getIsolateTag(\"_\$dart_js\");\n" +" t1 = \$._JS_INTEROP_INTERCEPTOR_TAG = A.getIsolateAffinityTag(_s9_);\n" " interceptor = \$constructor[t1];\n" " }\n" " if (interceptor != null)\n" @@ -277,7 +278,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " if (typeof \$constructor == \"function\") {\n" " t1 = \$._JS_INTEROP_INTERCEPTOR_TAG;\n" " if (t1 == null)\n" -" t1 = \$._JS_INTEROP_INTERCEPTOR_TAG = init.getIsolateTag(\"_\$dart_js\");\n" +" t1 = \$._JS_INTEROP_INTERCEPTOR_TAG = A.getIsolateAffinityTag(_s9_);\n" " Object.defineProperty(\$constructor, t1, {value: B.UnknownJavaScriptObject_methods, enumerable: false, writable: true, configurable: true});\n" " return B.UnknownJavaScriptObject_methods;\n" " }\n" @@ -1042,7 +1043,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " throw A.wrapException(A.UnsupportedError\$(\"Cannot modify unmodifiable Map\"));\n" " },\n" " unminifyOrTag(rawClassName) {\n" -" var preserved = init.mangledGlobalNames[rawClassName];\n" +" var preserved = A.unmangleGlobalNameIfPreservedAnyways(rawClassName);\n" " if (preserved != null)\n" " return preserved;\n" " return rawClassName;\n" @@ -2114,7 +2115,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " JsLinkedHashMap: function JsLinkedHashMap(t0) {\n" " var _ = this;\n" " _.__js_helper\$_length = 0;\n" -" _._last = _._first = _.__js_helper\$_rest = _.__js_helper\$_nums = _.__js_helper\$_strings = null;\n" +" _._last = _._first = _.__js_helper\$_rest = _._nums = _._strings = null;\n" " _._modifications = 0;\n" " _.\$ti = t0;\n" " },\n" @@ -2163,7 +2164,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " JsIdentityLinkedHashMap: function JsIdentityLinkedHashMap(t0) {\n" " var _ = this;\n" " _.__js_helper\$_length = 0;\n" -" _._last = _._first = _.__js_helper\$_rest = _.__js_helper\$_nums = _.__js_helper\$_strings = null;\n" +" _._last = _._first = _.__js_helper\$_rest = _._nums = _._strings = null;\n" " _._modifications = 0;\n" " _.\$ti = t0;\n" " },\n" @@ -2972,7 +2973,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " return \"?\";\n" " },\n" " _unminifyOrTag(rawClassName) {\n" -" var preserved = init.mangledGlobalNames[rawClassName];\n" +" var preserved = A.unmangleGlobalNameIfPreservedAnyways(rawClassName);\n" " if (preserved != null)\n" " return preserved;\n" " return rawClassName;\n" @@ -3013,7 +3014,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " probe = cache.get(recipe);\n" " if (probe != null)\n" " return probe;\n" -" rti = A._Parser_parse(A._Parser_create(universe, null, recipe, false));\n" +" rti = A._Universe__parseRecipe(universe, null, recipe, false);\n" " cache.set(recipe, rti);\n" " return rti;\n" " },\n" @@ -3025,7 +3026,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " probe = cache.get(recipe);\n" " if (probe != null)\n" " return probe;\n" -" rti = A._Parser_parse(A._Parser_create(universe, environment, recipe, true));\n" +" rti = A._Universe__parseRecipe(universe, environment, recipe, true);\n" " cache.set(recipe, rti);\n" " return rti;\n" " },\n" @@ -3042,6 +3043,9 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " cache.set(argumentsRecipe, rti);\n" " return rti;\n" " },\n" +" _Universe__parseRecipe(universe, environment, recipe, normalize) {\n" +" return A._Parser_parse(A._Parser_create(universe, environment, recipe, normalize));\n" +" },\n" " _Universe__installTypeTests(universe, rti) {\n" " rti._as = A._installSpecializedAsCheck;\n" " rti._is = A._installSpecializedIsTest;\n" @@ -3822,19 +3826,14 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " A.Timer__createTimer(B.Duration_0, type\$.void_Function._as(callback));\n" " },\n" " Timer__createTimer(duration, callback) {\n" -" var milliseconds = B.JSInt_methods._tdivFast\$1(duration._duration, 1000);\n" +" var milliseconds = B.JSInt_methods._tdivFast\$1(duration.inMicroseconds, 1000);\n" " return A._TimerImpl\$(milliseconds < 0 ? 0 : milliseconds, callback);\n" " },\n" " _TimerImpl\$(milliseconds, callback) {\n" -" var t1 = new A._TimerImpl(true);\n" +" var t1 = new A._TimerImpl();\n" " t1._TimerImpl\$2(milliseconds, callback);\n" " return t1;\n" " },\n" -" _TimerImpl\$periodic(milliseconds, callback) {\n" -" var t1 = new A._TimerImpl(false);\n" -" t1._TimerImpl\$periodic\$2(milliseconds, callback);\n" -" return t1;\n" -" },\n" " _makeAsyncAwaitCompleter(\$T) {\n" " return new A._AsyncAwaitCompleter(new A._Future(\$.Zone__current, \$T._eval\$1(\"_Future<0>\")), \$T._eval\$1(\"_AsyncAwaitCompleter<0>\"));\n" " },\n" @@ -3872,19 +3871,20 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " },\n" " _wrapJsFunctionForAsync(\$function) {\n" " var \$protected = function(fn, ERROR) {\n" -" return function(errorCode, result) {\n" -" while (true) {\n" -" try {\n" -" fn(errorCode, result);\n" -" break;\n" -" } catch (error) {\n" -" result = error;\n" -" errorCode = ERROR;\n" +" return function(errorCode, result) {\n" +" while (true) {\n" +" try {\n" +" fn(errorCode, result);\n" +" break;\n" +" } catch (error) {\n" +" result = error;\n" +" errorCode = ERROR;\n" +" }\n" " }\n" -" }\n" -" };\n" -" }(\$function, 1);\n" -" return \$.Zone__current.registerBinaryCallback\$3\$1(new A._wrapJsFunctionForAsync_closure(\$protected), type\$.void, type\$.int, type\$.dynamic);\n" +" };\n" +" }(\$function, 1),\n" +" t1 = \$.Zone__current;\n" +" return t1._registerBinaryCallbackZoned\$3\$2(t1, type\$.void_Function_int_dynamic._as(new A._wrapJsFunctionForAsync_closure(\$protected)), type\$.void, type\$.int, type\$.dynamic);\n" " },\n" " AsyncError_defaultStackTrace(error) {\n" " var stackTrace;\n" @@ -3940,9 +3940,9 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _interceptError(error, stackTrace) {\n" " var replacement, t1, t2,\n" " zone = \$.Zone__current;\n" -" if (zone === B.C__RootZone)\n" +" if (zone === B.Zone_jYP)\n" " return null;\n" -" replacement = zone.errorCallback\$2(error, stackTrace);\n" +" replacement = zone._errorCallbackZoned\$3(zone, error, stackTrace);\n" " if (replacement == null)\n" " return null;\n" " t1 = replacement.error;\n" @@ -3953,7 +3953,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " },\n" " _interceptUserError(error, stackTrace) {\n" " var replacement;\n" -" if (\$.Zone__current !== B.C__RootZone) {\n" +" if (\$.Zone__current !== B.Zone_jYP) {\n" " replacement = A._interceptError(error, stackTrace);\n" " if (replacement != null)\n" " return replacement;\n" @@ -3979,7 +3979,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " return t1;\n" " },\n" " _Future__chainCoreFuture(source, target, sync) {\n" -" var t2, t3, ignoreError, listeners, _box_0 = {},\n" +" var t2, t3, ignoreError, listeners, targetZone, _box_0 = {},\n" " t1 = _box_0.source = source;\n" " for (t2 = type\$._Future_dynamic; t3 = t1._state, (t3 & 4) !== 0; t1 = source) {\n" " source = t2._as(t1._resultOrListeners);\n" @@ -4013,7 +4013,8 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " return;\n" " }\n" " target._state ^= 2;\n" -" target._zone.scheduleMicrotask\$1(new A._Future__chainCoreFuture_closure(_box_0, target));\n" +" targetZone = target._zone;\n" +" targetZone._scheduleMicrotaskZoned\$2(targetZone, new A._Future__chainCoreFuture_closure(_box_0, target));\n" " },\n" " _Future__propagateToListeners(source, listeners) {\n" " var t2, t3, _box_0, t4, t5, hasError, asyncError, nextListener, nextListener0, sourceResult, t6, zone, oldZone, result, current, _box_1 = {},\n" @@ -4026,7 +4027,8 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " if (listeners == null) {\n" " if (hasError && (t4 & 1) === 0) {\n" " asyncError = t2._as(t1._resultOrListeners);\n" -" t1._zone.handleUncaughtError\$2(asyncError.error, asyncError.stackTrace);\n" +" t1 = t1._zone;\n" +" t1._handleUncaughtErrorZoned\$3(t1, asyncError.error, asyncError.stackTrace);\n" " }\n" " return;\n" " }\n" @@ -4049,15 +4051,10 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t6 = true;\n" " if (t6) {\n" " zone = t1.result._zone;\n" -" if (hasError) {\n" +" if (hasError && t4._zone._handleUncaughtErrorFunction != zone._handleUncaughtErrorFunction) {\n" +" t2._as(sourceResult);\n" " t1 = t4._zone;\n" -" t1 = !(t1 === zone || t1.get\$errorZone() === zone.get\$errorZone());\n" -" } else\n" -" t1 = false;\n" -" if (t1) {\n" -" t1 = _box_1.source;\n" -" asyncError = t2._as(t1._resultOrListeners);\n" -" t1._zone.handleUncaughtError\$2(asyncError.error, asyncError.stackTrace);\n" +" t1._handleUncaughtErrorZoned\$3(t1, sourceResult.error, sourceResult.stackTrace);\n" " return;\n" " }\n" " oldZone = \$.Zone__current;\n" @@ -4065,7 +4062,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " \$.Zone__current = zone;\n" " else\n" " oldZone = null;\n" -" t1 = _box_0.listener.state;\n" +" t1 = t1.state;\n" " if ((t1 & 15) === 8)\n" " new A._Future__propagateToListeners_handleWhenCompleteCallback(_box_0, _box_1, hasError).call\$0();\n" " else if (t5) {\n" @@ -4116,10 +4113,12 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " }\n" " },\n" " _registerErrorHandler(errorHandler, zone) {\n" -" if (type\$.dynamic_Function_Object_StackTrace._is(errorHandler))\n" -" return zone.registerBinaryCallback\$3\$1(errorHandler, type\$.dynamic, type\$.Object, type\$.StackTrace);\n" -" if (type\$.dynamic_Function_Object._is(errorHandler))\n" -" return zone.registerUnaryCallback\$2\$1(errorHandler, type\$.dynamic, type\$.Object);\n" +" var t1 = type\$.dynamic_Function_Object_StackTrace;\n" +" if (t1._is(errorHandler))\n" +" return zone._registerBinaryCallbackZoned\$3\$2(zone, t1._as(errorHandler), type\$.dynamic, type\$.Object, type\$.StackTrace);\n" +" t1 = type\$.dynamic_Function_Object;\n" +" if (t1._is(errorHandler))\n" +" return zone._registerUnaryCallbackZoned\$2\$2(zone, t1._as(errorHandler), type\$.dynamic, type\$.Object);\n" " throw A.wrapException(A.ArgumentError\$value(errorHandler, \"onError\", string\$.Error_));\n" " },\n" " _microtaskLoop() {\n" @@ -4176,22 +4175,16 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " }\n" " },\n" " scheduleMicrotask(callback) {\n" -" var t1, _null = null,\n" -" currentZone = \$.Zone__current;\n" -" if (B.C__RootZone === currentZone) {\n" -" A._rootScheduleMicrotask(_null, _null, B.C__RootZone, callback);\n" +" var currentZone = \$.Zone__current;\n" +" if (B.Zone_jYP === currentZone) {\n" +" A._rootScheduleMicrotask(B.Zone_jYP, callback);\n" " return;\n" " }\n" -" if (B.C__RootZone === currentZone.get\$_scheduleMicrotask().zone)\n" -" t1 = B.C__RootZone.get\$errorZone() === currentZone.get\$errorZone();\n" -" else\n" -" t1 = false;\n" -" if (t1) {\n" -" A._rootScheduleMicrotask(_null, _null, currentZone, currentZone.registerCallback\$1\$1(callback, type\$.void));\n" +" if (currentZone._scheduleMicrotaskFunction == null && currentZone._handleUncaughtErrorFunction == null) {\n" +" A._rootScheduleMicrotask(currentZone, currentZone._registerCallbackZoned\$1\$2(currentZone, callback, type\$.void));\n" " return;\n" " }\n" -" t1 = \$.Zone__current;\n" -" t1.scheduleMicrotask\$1(t1.bindCallbackGuarded\$1(callback));\n" +" currentZone._scheduleMicrotaskZoned\$2(currentZone, currentZone.bindCallbackGuarded\$1(callback));\n" " },\n" " StreamIterator_StreamIterator(stream, \$T) {\n" " A.checkNotNullable(stream, \"stream\", type\$.Object);\n" @@ -4202,7 +4195,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " return new A._AsyncStreamController(_null, _null, _null, _null, \$T._eval\$1(\"_AsyncStreamController<0>\"));\n" " },\n" " _runGuarded(notificationHandler) {\n" -" var e, s, exception;\n" +" var e, s, exception, t1;\n" " if (notificationHandler == null)\n" " return;\n" " try {\n" @@ -4210,28 +4203,31 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " } catch (exception) {\n" " e = A.unwrapException(exception);\n" " s = A.getTraceFromException(exception);\n" -" \$.Zone__current.handleUncaughtError\$2(e, s);\n" +" t1 = \$.Zone__current;\n" +" t1._handleUncaughtErrorZoned\$3(t1, A._asObject(e), type\$.StackTrace._as(s));\n" " }\n" " },\n" " _BufferingStreamSubscription__registerDataHandler(zone, handleData, \$T) {\n" " var t1 = handleData == null ? A.async___nullDataHandler\$closure() : handleData;\n" -" return zone.registerUnaryCallback\$2\$1(t1, type\$.void, \$T);\n" +" return zone._registerUnaryCallbackZoned\$2\$2(zone, type\$.\$env_1_1_void._bind\$1(\$T)._eval\$1(\"1(2)\")._as(t1), type\$.void, \$T);\n" " },\n" " _BufferingStreamSubscription__registerErrorHandler(zone, handleError) {\n" " if (handleError == null)\n" " handleError = A.async___nullErrorHandler\$closure();\n" " if (type\$.void_Function_Object_StackTrace._is(handleError))\n" -" return zone.registerBinaryCallback\$3\$1(handleError, type\$.dynamic, type\$.Object, type\$.StackTrace);\n" +" return zone._registerBinaryCallbackZoned\$3\$2(zone, type\$.dynamic_Function_Object_StackTrace._as(handleError), type\$.dynamic, type\$.Object, type\$.StackTrace);\n" " if (type\$.void_Function_Object._is(handleError))\n" -" return zone.registerUnaryCallback\$2\$1(handleError, type\$.dynamic, type\$.Object);\n" +" return zone._registerUnaryCallbackZoned\$2\$2(zone, type\$.dynamic_Function_Object._as(handleError), type\$.dynamic, type\$.Object);\n" " throw A.wrapException(A.ArgumentError\$(string\$.handle, null));\n" " },\n" " _nullDataHandler(value) {\n" " },\n" " _nullErrorHandler(error, stackTrace) {\n" +" var t1;\n" " A._asObject(error);\n" " type\$.StackTrace._as(stackTrace);\n" -" \$.Zone__current.handleUncaughtError\$2(error, stackTrace);\n" +" t1 = \$.Zone__current;\n" +" t1._handleUncaughtErrorZoned\$3(t1, error, stackTrace);\n" " },\n" " _nullDoneHandler() {\n" " },\n" @@ -4244,20 +4240,35 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " },\n" " Timer_Timer(duration, callback) {\n" " var t1 = \$.Zone__current;\n" -" if (t1 === B.C__RootZone)\n" -" return t1.createTimer\$2(duration, callback);\n" -" return t1.createTimer\$2(duration, t1.bindCallbackGuarded\$1(callback));\n" +" if (t1 === B.Zone_jYP)\n" +" return t1._createTimerZoned\$3(t1, duration, type\$.void_Function._as(callback));\n" +" return t1._createTimerZoned\$3(t1, duration, type\$.void_Function._as(t1.bindCallbackGuarded\$1(callback)));\n" " },\n" " runZonedGuarded(body, onError, \$R) {\n" -" var error, stackTrace, t1, exception, _null = null, zoneSpecification = null, zoneValues = null,\n" +" var error, stackTrace, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, newZone, exception, _null = null, zoneSpecification = null, zoneValues = null,\n" " parentZone = \$.Zone__current,\n" -" errorHandler = new A.runZonedGuarded_closure(parentZone, onError);\n" +" t1 = new A.runZonedGuarded_errorHandler(parentZone, onError);\n" " if (zoneSpecification == null)\n" -" zoneSpecification = new A._ZoneSpecification(errorHandler, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null);\n" -" else\n" -" zoneSpecification = A.ZoneSpecification_ZoneSpecification\$from(zoneSpecification, errorHandler);\n" +" zoneSpecification = new A.ZoneSpecification(t1, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null, _null);\n" +" else {\n" +" t2 = zoneSpecification;\n" +" t3 = t2.run;\n" +" t4 = t2.runUnary;\n" +" t5 = t2.runBinary;\n" +" t6 = t2.registerCallback;\n" +" t7 = t2.registerUnaryCallback;\n" +" t8 = t2.registerBinaryCallback;\n" +" t9 = t2.errorCallback;\n" +" t10 = t2.scheduleMicrotask;\n" +" t11 = t2.createTimer;\n" +" t12 = t2.createPeriodicTimer;\n" +" t13 = t2.print;\n" +" t2 = t2.fork;\n" +" zoneSpecification = new A.ZoneSpecification(t1, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t2);\n" +" }\n" " try {\n" -" t1 = parentZone.fork\$2\$specification\$zoneValues(zoneSpecification, zoneValues).run\$1\$1(body, \$R);\n" +" newZone = parentZone._forkZoned\$3(parentZone, zoneSpecification, zoneValues);\n" +" t1 = newZone._runZoned\$1\$2(newZone, body, \$R);\n" " return t1;\n" " } catch (exception) {\n" " error = A.unwrapException(exception);\n" @@ -4266,128 +4277,24 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " }\n" " return _null;\n" " },\n" -" _rootHandleUncaughtError(\$self, \$parent, zone, error, stackTrace) {\n" -" A._rootHandleError(error, type\$.StackTrace._as(stackTrace));\n" +" ZoneDelegate\$_() {\n" +" return new A.ZoneDelegate(B.Zone_jYP);\n" " },\n" -" _rootHandleError(error, stackTrace) {\n" -" A._schedulePriorityAsyncCallback(new A._rootHandleError_closure(error, stackTrace));\n" +" _rootHandleUncaughtError(error, stackTrace) {\n" +" A._schedulePriorityAsyncCallback(new A._rootHandleUncaughtError_closure(error, stackTrace));\n" " },\n" -" _rootRun(\$self, \$parent, zone, f, \$R) {\n" -" var old, t1;\n" -" type\$.nullable_Zone._as(\$self);\n" -" type\$.nullable_ZoneDelegate._as(\$parent);\n" -" type\$.Zone._as(zone);\n" -" \$R._eval\$1(\"0()\")._as(f);\n" -" t1 = \$.Zone__current;\n" -" if (t1 === zone)\n" -" return f.call\$0();\n" -" \$.Zone__current = zone;\n" -" old = t1;\n" -" try {\n" -" t1 = f.call\$0();\n" -" return t1;\n" -" } finally {\n" -" \$.Zone__current = old;\n" -" }\n" -" },\n" -" _rootRunUnary(\$self, \$parent, zone, f, arg, \$R, \$T) {\n" -" var old, t1;\n" -" type\$.nullable_Zone._as(\$self);\n" -" type\$.nullable_ZoneDelegate._as(\$parent);\n" -" type\$.Zone._as(zone);\n" -" \$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(f);\n" -" \$T._as(arg);\n" -" t1 = \$.Zone__current;\n" -" if (t1 === zone)\n" -" return f.call\$1(arg);\n" -" \$.Zone__current = zone;\n" -" old = t1;\n" -" try {\n" -" t1 = f.call\$1(arg);\n" -" return t1;\n" -" } finally {\n" -" \$.Zone__current = old;\n" -" }\n" -" },\n" -" _rootRunBinary(\$self, \$parent, zone, f, arg1, arg2, \$R, \$T1, \$T2) {\n" -" var old, t1;\n" -" type\$.nullable_Zone._as(\$self);\n" -" type\$.nullable_ZoneDelegate._as(\$parent);\n" -" type\$.Zone._as(zone);\n" -" \$R._eval\$1(\"@<0>\")._bind\$1(\$T1)._bind\$1(\$T2)._eval\$1(\"1(2,3)\")._as(f);\n" -" \$T1._as(arg1);\n" -" \$T2._as(arg2);\n" -" t1 = \$.Zone__current;\n" -" if (t1 === zone)\n" -" return f.call\$2(arg1, arg2);\n" -" \$.Zone__current = zone;\n" -" old = t1;\n" -" try {\n" -" t1 = f.call\$2(arg1, arg2);\n" -" return t1;\n" -" } finally {\n" -" \$.Zone__current = old;\n" -" }\n" -" },\n" -" _rootRegisterCallback(\$self, \$parent, zone, f, \$R) {\n" -" return \$R._eval\$1(\"0()\")._as(f);\n" -" },\n" -" _rootRegisterUnaryCallback(\$self, \$parent, zone, f, \$R, \$T) {\n" -" return \$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(f);\n" -" },\n" -" _rootRegisterBinaryCallback(\$self, \$parent, zone, f, \$R, \$T1, \$T2) {\n" -" return \$R._eval\$1(\"@<0>\")._bind\$1(\$T1)._bind\$1(\$T2)._eval\$1(\"1(2,3)\")._as(f);\n" -" },\n" -" _rootErrorCallback(\$self, \$parent, zone, error, stackTrace) {\n" -" type\$.nullable_StackTrace._as(stackTrace);\n" -" return null;\n" -" },\n" -" _rootScheduleMicrotask(\$self, \$parent, zone, f) {\n" -" var t1, t2;\n" -" type\$.void_Function._as(f);\n" -" if (B.C__RootZone !== zone) {\n" -" t1 = B.C__RootZone.get\$errorZone();\n" -" t2 = zone.get\$errorZone();\n" -" f = t1 !== t2 ? zone.bindCallbackGuarded\$1(f) : zone.bindCallback\$1\$1(f, type\$.void);\n" -" }\n" -" A._scheduleAsyncCallback(f);\n" +" _rootScheduleMicrotask(zone, callback) {\n" +" if (B.Zone_jYP !== zone)\n" +" callback = zone._handleUncaughtErrorFunction != null ? zone.bindCallbackGuarded\$1(callback) : zone.bindCallback\$1\$1(callback, type\$.void);\n" +" A._scheduleAsyncCallback(callback);\n" " },\n" -" _rootCreateTimer(\$self, \$parent, zone, duration, callback) {\n" -" type\$.Duration._as(duration);\n" -" type\$.void_Function._as(callback);\n" -" return A.Timer__createTimer(duration, B.C__RootZone !== zone ? zone.bindCallback\$1\$1(callback, type\$.void) : callback);\n" -" },\n" -" _rootCreatePeriodicTimer(\$self, \$parent, zone, duration, callback) {\n" -" var milliseconds;\n" -" type\$.Duration._as(duration);\n" -" type\$.void_Function_Timer._as(callback);\n" -" if (B.C__RootZone !== zone)\n" -" callback = zone.bindUnaryCallback\$2\$1(callback, type\$.void, type\$.Timer);\n" -" milliseconds = B.JSInt_methods._tdivFast\$1(duration._duration, 1000);\n" -" return A._TimerImpl\$periodic(milliseconds < 0 ? 0 : milliseconds, callback);\n" -" },\n" -" _rootPrint(\$self, \$parent, zone, line) {\n" -" A.printString(A._asString(line));\n" -" },\n" -" _printToZone0(line) {\n" -" \$.Zone__current.print\$1(line);\n" -" },\n" -" _rootFork(\$self, \$parent, zone, specification, zoneValues) {\n" -" var valueMap, t1, handleUncaughtError;\n" -" type\$.nullable_ZoneSpecification._as(specification);\n" -" type\$.nullable_Map_of_nullable_Object_and_nullable_Object._as(zoneValues);\n" -" \$._printToZone = A.async___printToZone\$closure();\n" -" valueMap = zone.get\$_map();\n" -" 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);\n" -" handleUncaughtError = specification.handleUncaughtError;\n" -" if (handleUncaughtError != null)\n" -" t1._handleUncaughtError = new A._ZoneFunction(t1, handleUncaughtError, type\$._ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_Object_StackTrace);\n" +" _rootFork(zone, specification, zoneValues) {\n" +" var t1 = new A.ZoneDelegate(B.Zone_jYP),\n" +" t2 = new A._ZoneHandleUncaughtError(B.Zone_jYP, specification.handleUncaughtError);\n" +" t1 = t1._zone = new A.Zone(zone, t1, zone._runFunction, zone._runUnaryFunction, zone._runBinaryFunction, zone._registerCallbackFunction, zone._registerUnaryCallbackFunction, zone._registerBinaryCallbackFunction, zone._errorCallbackFunction, zone._scheduleMicrotaskFunction, zone._createTimerFunction, zone._createPeriodicTimerFunction, zone._printFunction, zone._forkFunction, t2, zone._zoneValues);\n" +" t2.zone = t1;\n" " return t1;\n" " },\n" -" ZoneSpecification_ZoneSpecification\$from(other, handleUncaughtError) {\n" -" var t1 = handleUncaughtError == null ? other.handleUncaughtError : handleUncaughtError;\n" -" return new A._ZoneSpecification(t1, other.run, other.runUnary, other.runBinary, other.registerCallback, other.registerUnaryCallback, other.registerBinaryCallback, other.errorCallback, other.scheduleMicrotask, other.createTimer, other.createPeriodicTimer, other.print, other.fork);\n" -" },\n" " _AsyncRun__initializeScheduleImmediate_internalCallback: function _AsyncRun__initializeScheduleImmediate_internalCallback(t0) {\n" " this._box_0 = t0;\n" " },\n" @@ -4402,22 +4309,13 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _AsyncRun__scheduleImmediateWithSetImmediate_internalCallback: function _AsyncRun__scheduleImmediateWithSetImmediate_internalCallback(t0) {\n" " this.callback = t0;\n" " },\n" -" _TimerImpl: function _TimerImpl(t0) {\n" -" this._once = t0;\n" +" _TimerImpl: function _TimerImpl() {\n" " this._handle = null;\n" -" this._tick = 0;\n" " },\n" " _TimerImpl_internalCallback: function _TimerImpl_internalCallback(t0, t1) {\n" " this.\$this = t0;\n" " this.callback = t1;\n" " },\n" -" _TimerImpl\$periodic_closure: function _TimerImpl\$periodic_closure(t0, t1, t2, t3) {\n" -" var _ = this;\n" -" _.\$this = t0;\n" -" _.milliseconds = t1;\n" -" _.start = t2;\n" -" _.callback = t3;\n" -" },\n" " _AsyncAwaitCompleter: function _AsyncAwaitCompleter(t0, t1) {\n" " this._future = t0;\n" " this.isSync = false;\n" @@ -4696,88 +4594,55 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " this._source = t1;\n" " this.\$ti = t2;\n" " },\n" -" _ZoneFunction: function _ZoneFunction(t0, t1, t2) {\n" +" _ZoneHandleUncaughtError: function _ZoneHandleUncaughtError(t0, t1) {\n" " this.zone = t0;\n" " this.\$function = t1;\n" -" this.\$ti = t2;\n" -" },\n" -" _Zone: function _Zone() {\n" " },\n" -" _CustomZone: function _CustomZone(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) {\n" +" Zone: function Zone(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15) {\n" " var _ = this;\n" -" _._run = t0;\n" -" _._runUnary = t1;\n" -" _._runBinary = t2;\n" -" _._registerCallback = t3;\n" -" _._registerUnaryCallback = t4;\n" -" _._registerBinaryCallback = t5;\n" -" _._errorCallback = t6;\n" -" _._scheduleMicrotask = t7;\n" -" _._createTimer = t8;\n" -" _._createPeriodicTimer = t9;\n" -" _._print = t10;\n" -" _._fork = t11;\n" -" _._handleUncaughtError = t12;\n" -" _._delegateCache = null;\n" -" _.parent = t13;\n" -" _._map = t14;\n" -" },\n" -" _CustomZone_bindCallback_closure: function _CustomZone_bindCallback_closure(t0, t1, t2) {\n" +" _._parent = t0;\n" +" _._delegate = t1;\n" +" _._runFunction = t2;\n" +" _._runUnaryFunction = t3;\n" +" _._runBinaryFunction = t4;\n" +" _._registerCallbackFunction = t5;\n" +" _._registerUnaryCallbackFunction = t6;\n" +" _._registerBinaryCallbackFunction = t7;\n" +" _._errorCallbackFunction = t8;\n" +" _._scheduleMicrotaskFunction = t9;\n" +" _._createTimerFunction = t10;\n" +" _._createPeriodicTimerFunction = t11;\n" +" _._printFunction = t12;\n" +" _._forkFunction = t13;\n" +" _._handleUncaughtErrorFunction = t14;\n" +" _._zoneValues = t15;\n" +" },\n" +" Zone_bindCallback_closure: function Zone_bindCallback_closure(t0, t1, t2) {\n" " this.\$this = t0;\n" " this.registered = t1;\n" " this.R = t2;\n" " },\n" -" _CustomZone_bindUnaryCallback_closure: function _CustomZone_bindUnaryCallback_closure(t0, t1, t2, t3) {\n" -" var _ = this;\n" -" _.\$this = t0;\n" -" _.registered = t1;\n" -" _.T = t2;\n" -" _.R = t3;\n" -" },\n" -" _CustomZone_bindCallbackGuarded_closure: function _CustomZone_bindCallbackGuarded_closure(t0, t1) {\n" +" Zone_bindCallbackGuarded_closure: function Zone_bindCallbackGuarded_closure(t0, t1) {\n" " this.\$this = t0;\n" " this.registered = t1;\n" " },\n" -" _CustomZone_bindUnaryCallbackGuarded_closure: function _CustomZone_bindUnaryCallbackGuarded_closure(t0, t1, t2) {\n" +" Zone_bindUnaryCallbackGuarded_closure: function Zone_bindUnaryCallbackGuarded_closure(t0, t1, t2) {\n" " this.\$this = t0;\n" " this.registered = t1;\n" " this.T = t2;\n" " },\n" -" _RootZone: function _RootZone() {\n" -" },\n" -" _RootZone_bindCallback_closure: function _RootZone_bindCallback_closure(t0, t1, t2) {\n" -" this.\$this = t0;\n" -" this.f = t1;\n" -" this.R = t2;\n" -" },\n" -" _RootZone_bindUnaryCallback_closure: function _RootZone_bindUnaryCallback_closure(t0, t1, t2, t3) {\n" -" var _ = this;\n" -" _.\$this = t0;\n" -" _.f = t1;\n" -" _.T = t2;\n" -" _.R = t3;\n" -" },\n" -" _RootZone_bindCallbackGuarded_closure: function _RootZone_bindCallbackGuarded_closure(t0, t1) {\n" -" this.\$this = t0;\n" -" this.f = t1;\n" -" },\n" -" _RootZone_bindUnaryCallbackGuarded_closure: function _RootZone_bindUnaryCallbackGuarded_closure(t0, t1, t2) {\n" -" this.\$this = t0;\n" -" this.f = t1;\n" -" this.T = t2;\n" -" },\n" -" runZonedGuarded_closure: function runZonedGuarded_closure(t0, t1) {\n" +" runZonedGuarded_errorHandler: function runZonedGuarded_errorHandler(t0, t1) {\n" " this.parentZone = t0;\n" " this.onError = t1;\n" " },\n" -" _ZoneDelegate: function _ZoneDelegate(t0) {\n" -" this._delegationTarget = t0;\n" +" ZoneDelegate: function ZoneDelegate(t0) {\n" +" this._zone = t0;\n" " },\n" -" _rootHandleError_closure: function _rootHandleError_closure(t0, t1) {\n" +" _rootHandleUncaughtError_closure: function _rootHandleUncaughtError_closure(t0, t1) {\n" " this.error = t0;\n" " this.stackTrace = t1;\n" " },\n" -" _ZoneSpecification: function _ZoneSpecification(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) {\n" +" ZoneSpecification: function ZoneSpecification(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) {\n" " var _ = this;\n" " _.handleUncaughtError = t0;\n" " _.run = t1;\n" @@ -4882,23 +4747,23 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _HashMap: function _HashMap(t0) {\n" " var _ = this;\n" " _._collection\$_length = 0;\n" -" _._keys = _._collection\$_rest = _._nums = _._strings = null;\n" +" _._collection\$_keys = _._collection\$_rest = _._collection\$_nums = _._collection\$_strings = null;\n" " _.\$ti = t0;\n" " },\n" " _IdentityHashMap: function _IdentityHashMap(t0) {\n" " var _ = this;\n" " _._collection\$_length = 0;\n" -" _._keys = _._collection\$_rest = _._nums = _._strings = null;\n" +" _._collection\$_keys = _._collection\$_rest = _._collection\$_nums = _._collection\$_strings = null;\n" " _.\$ti = t0;\n" " },\n" " _HashMapKeyIterable: function _HashMapKeyIterable(t0, t1) {\n" -" this._collection\$_map = t0;\n" +" this._map = t0;\n" " this.\$ti = t1;\n" " },\n" " _HashMapKeyIterator: function _HashMapKeyIterator(t0, t1, t2) {\n" " var _ = this;\n" -" _._collection\$_map = t0;\n" -" _._keys = t1;\n" +" _._map = t0;\n" +" _._collection\$_keys = t1;\n" " _._offset = 0;\n" " _._collection\$_current = null;\n" " _.\$ti = t2;\n" @@ -4909,7 +4774,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _._hashCode = t1;\n" " _._validKey = t2;\n" " _.__js_helper\$_length = 0;\n" -" _._last = _._first = _.__js_helper\$_rest = _.__js_helper\$_nums = _.__js_helper\$_strings = null;\n" +" _._last = _._first = _.__js_helper\$_rest = _._nums = _._strings = null;\n" " _._modifications = 0;\n" " _.\$ti = t3;\n" " },\n" @@ -4919,7 +4784,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _HashSet: function _HashSet(t0) {\n" " var _ = this;\n" " _._collection\$_length = 0;\n" -" _._collection\$_elements = _._collection\$_rest = _._nums = _._strings = null;\n" +" _._collection\$_elements = _._collection\$_rest = _._collection\$_nums = _._collection\$_strings = null;\n" " _.\$ti = t0;\n" " },\n" " _HashSetIterator: function _HashSetIterator(t0, t1, t2) {\n" @@ -4943,7 +4808,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " MapView: function MapView() {\n" " },\n" " UnmodifiableMapView: function UnmodifiableMapView(t0, t1) {\n" -" this._collection\$_map = t0;\n" +" this._map = t0;\n" " this.\$ti = t1;\n" " },\n" " ListQueue: function ListQueue(t0, t1) {\n" @@ -5108,7 +4973,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " this._data = null;\n" " },\n" " _JsonMapKeyIterable: function _JsonMapKeyIterable(t0) {\n" -" this._parent = t0;\n" +" this._convert\$_parent = t0;\n" " },\n" " _Utf8Decoder__decoder_closure: function _Utf8Decoder__decoder_closure() {\n" " },\n" @@ -6830,7 +6695,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " this.isUtc = t2;\n" " },\n" " Duration: function Duration(t0) {\n" -" this._duration = t0;\n" +" this.inMicroseconds = t0;\n" " },\n" " _Enum: function _Enum() {\n" " },\n" @@ -7509,7 +7374,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _readStreamBody\$body(request, response, controller) {\n" " var \$async\$goto = 0,\n" " \$async\$completer = A._makeAsyncAwaitCompleter(type\$.void),\n" -" \$async\$returnValue, \$async\$handler = 2, \$async\$errorStack = [], chunk, e, s, t2, t3, t4, t5, t6, t7, exception, varData, t8, t9, _box_0, t1, reader, \$async\$exception;\n" +" \$async\$returnValue, \$async\$handler = 2, \$async\$errorStack = [], chunk, e, s, t2, t3, t4, t5, exception, t6, t7, _box_0, t1, reader, \$async\$exception;\n" " var \$async\$_readStreamBody = A._wrapJsFunctionForAsync(function(\$async\$errorCode, \$async\$result) {\n" " if (\$async\$errorCode === 1) {\n" " \$async\$errorStack.push(\$async\$result);\n" @@ -7539,14 +7404,14 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _box_0.hadError = _box_0.cancelled = false;\n" " controller.set\$onResume(new A._readStreamBody_closure(_box_0));\n" " controller.set\$onCancel(new A._readStreamBody_closure0(_box_0, reader, request));\n" -" t1 = type\$.NativeUint8List, t2 = controller.\$ti, t3 = t2._precomputed1, t4 = type\$.JSObject, t2 = t2._eval\$1(\"_ControllerSubscription<1>\"), t5 = type\$._StreamControllerAddStreamState_nullable_Object, t6 = type\$._Future_void, t7 = type\$._AsyncCompleter_void;\n" +" t1 = type\$.NativeUint8List, t2 = controller.\$ti._precomputed1, t3 = type\$.JSObject, t4 = type\$._Future_void, t5 = type\$._AsyncCompleter_void;\n" " case 6:\n" " // for condition\n" " // trivial condition\n" " chunk = null;\n" " \$async\$handler = 9;\n" " \$async\$goto = 12;\n" -" return A._asyncAwait(A.promiseToFuture(A._asJSObject(reader.read()), t4), \$async\$_readStreamBody);\n" +" return A._asyncAwait(A.promiseToFuture(A._asJSObject(reader.read()), t3), \$async\$_readStreamBody);\n" " case 12:\n" " // returning from await.\n" " chunk = \$async\$result;\n" @@ -7566,14 +7431,13 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " // then\n" " _box_0.hadError = true;\n" " t1 = A._toClientException(e, request);\n" -" t3 = type\$.nullable_StackTrace._as(s);\n" -" t4 = controller._state;\n" -" if (t4 >= 4)\n" +" t2 = type\$.nullable_StackTrace._as(s);\n" +" t3 = controller._state;\n" +" if (t3 >= 4)\n" " A.throwExpression(controller._badEventState\$0());\n" -" if ((t4 & 1) !== 0) {\n" -" varData = controller._varData;\n" -" t6 = t2._as((t4 & 8) !== 0 ? t5._as(varData).get\$_varData() : varData);\n" -" t6._addError\$2(t1, t3 == null ? B._StringStackTrace_OdL : t3);\n" +" if ((t3 & 1) !== 0) {\n" +" t3 = controller.get\$_subscription();\n" +" t3._addError\$2(t1, t2 == null ? B._StringStackTrace_OdL : t2);\n" " }\n" " \$async\$goto = 15;\n" " return A._asyncAwait(controller.close\$0(), \$async\$_readStreamBody);\n" @@ -7600,31 +7464,23 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " \$async\$goto = 7;\n" " break;\n" " } else {\n" -" t8 = chunk.value;\n" -" t8.toString;\n" -" t8 = t3._as(t1._as(t8));\n" -" t9 = controller._state;\n" -" if (t9 >= 4)\n" +" t6 = chunk.value;\n" +" t6.toString;\n" +" t6 = t2._as(t1._as(t6));\n" +" t7 = controller._state;\n" +" if (t7 >= 4)\n" " A.throwExpression(controller._badEventState\$0());\n" -" if ((t9 & 1) !== 0) {\n" -" varData = controller._varData;\n" -" t2._as((t9 & 8) !== 0 ? t5._as(varData).get\$_varData() : varData)._add\$1(t8);\n" -" }\n" +" if ((t7 & 1) !== 0)\n" +" controller.get\$_subscription()._add\$1(t6);\n" " }\n" -" t8 = controller._state;\n" -" if ((t8 & 1) !== 0) {\n" -" varData = controller._varData;\n" -" t9 = (t2._as((t8 & 8) !== 0 ? t5._as(varData).get\$_varData() : varData)._state & 4) !== 0;\n" -" t8 = t9;\n" -" } else\n" -" t8 = (t8 & 2) === 0;\n" -" \$async\$goto = t8 ? 16 : 17;\n" +" t6 = controller._state;\n" +" \$async\$goto = ((t6 & 1) !== 0 ? (controller.get\$_subscription()._state & 4) !== 0 : (t6 & 2) === 0) ? 16 : 17;\n" " break;\n" " case 16:\n" " // then\n" -" t8 = _box_0.resumeSignal;\n" +" t6 = _box_0.resumeSignal;\n" " \$async\$goto = 18;\n" -" return A._asyncAwait((t8 == null ? _box_0.resumeSignal = new A._AsyncCompleter(new A._Future(\$.Zone__current, t6), t7) : t8).future, \$async\$_readStreamBody);\n" +" return A._asyncAwait((t6 == null ? _box_0.resumeSignal = new A._AsyncCompleter(new A._Future(\$.Zone__current, t4), t5) : t6).future, \$async\$_readStreamBody);\n" " case 18:\n" " // returning from await.\n" " case 17:\n" @@ -8321,7 +8177,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " },\n" " _wrapZone(callback, \$T) {\n" " var t1 = \$.Zone__current;\n" -" if (t1 === B.C__RootZone)\n" +" if (t1 === B.Zone_jYP)\n" " return callback;\n" " return t1.bindUnaryCallbackGuarded\$1\$1(callback, \$T);\n" " },\n" @@ -9085,6 +8941,9 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " JSArrayExtension_toDartIterable_closure: function JSArrayExtension_toDartIterable_closure(t0) {\n" " this.T = t0;\n" " },\n" +" unmangleGlobalNameIfPreservedAnyways(\$name) {\n" +" return init.mangledGlobalNames[\$name];\n" +" },\n" " printString(string) {\n" " if (typeof dartPrint == \"function\") {\n" " dartPrint(string);\n" @@ -9137,7 +8996,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " },\n" " encodingForContentTypeHeader(contentTypeHeader) {\n" " var t1,\n" -" charset = contentTypeHeader.parameters._collection\$_map.\$index(0, \"charset\");\n" +" charset = contentTypeHeader.parameters._map.\$index(0, \"charset\");\n" " if (contentTypeHeader.type === \"application\" && contentTypeHeader.subtype === \"json\" && charset == null)\n" " return B.C_Utf8Codec;\n" " if (charset != null) {\n" @@ -9828,12 +9687,6 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " return result;\n" " return result + other;\n" " },\n" -" \$tdiv(receiver, other) {\n" -" if ((receiver | 0) === receiver)\n" -" if (other >= 1 || other < -1)\n" -" return receiver / other | 0;\n" -" return this._tdivSlow\$1(receiver, other);\n" -" },\n" " _tdivFast\$1(receiver, other) {\n" " return (receiver | 0) === receiver ? receiver / other | 0 : this._tdivSlow\$1(receiver, other);\n" " },\n" @@ -10068,20 +9921,30 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " return this.__internal\$_source.cancel\$0();\n" " },\n" " onData\$1(handleData) {\n" -" var t1 = this.\$ti;\n" +" var t2,\n" +" t1 = this.\$ti;\n" " t1._eval\$1(\"~(2)?\")._as(handleData);\n" -" this.__internal\$_handleData = handleData == null ? null : this.__internal\$_zone.registerUnaryCallback\$2\$1(handleData, type\$.dynamic, t1._rest[1]);\n" +" if (handleData == null)\n" +" t1 = null;\n" +" else {\n" +" t2 = this.__internal\$_zone;\n" +" t1 = t1._rest[1];\n" +" t1 = t2._registerUnaryCallbackZoned\$2\$2(t2, type\$.\$env_1_1_dynamic._bind\$1(t1)._eval\$1(\"1(2)\")._as(handleData), type\$.dynamic, t1);\n" +" }\n" +" this.__internal\$_handleData = t1;\n" " },\n" " onError\$1(handleError) {\n" -" var _this = this;\n" +" var t1, _this = this;\n" " _this.__internal\$_source.onError\$1(handleError);\n" " if (handleError == null)\n" " _this.__internal\$_handleError = null;\n" -" else if (type\$.void_Function_Object_StackTrace._is(handleError))\n" -" _this.__internal\$_handleError = _this.__internal\$_zone.registerBinaryCallback\$3\$1(handleError, type\$.dynamic, type\$.Object, type\$.StackTrace);\n" -" else if (type\$.void_Function_Object._is(handleError))\n" -" _this.__internal\$_handleError = _this.__internal\$_zone.registerUnaryCallback\$2\$1(handleError, type\$.dynamic, type\$.Object);\n" -" else\n" +" else if (type\$.void_Function_Object_StackTrace._is(handleError)) {\n" +" t1 = _this.__internal\$_zone;\n" +" _this.__internal\$_handleError = t1._registerBinaryCallbackZoned\$3\$2(t1, type\$.dynamic_Function_Object_StackTrace._as(handleError), type\$.dynamic, type\$.Object, type\$.StackTrace);\n" +" } else if (type\$.void_Function_Object._is(handleError)) {\n" +" t1 = _this.__internal\$_zone;\n" +" _this.__internal\$_handleError = t1._registerUnaryCallbackZoned\$2\$2(t1, type\$.dynamic_Function_Object._as(handleError), type\$.dynamic, type\$.Object);\n" +" } else\n" " throw A.wrapException(A.ArgumentError\$(string\$.handle, null));\n" " },\n" " __internal\$_onData\$1(data) {\n" @@ -10098,9 +9961,10 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " error = A.unwrapException(exception);\n" " stack = A.getTraceFromException(exception);\n" " handleError = _this.__internal\$_handleError;\n" -" if (handleError == null)\n" -" _this.__internal\$_zone.handleUncaughtError\$2(error, stack);\n" -" else {\n" +" if (handleError == null) {\n" +" t1 = _this.__internal\$_zone;\n" +" t1._handleUncaughtErrorZoned\$3(t1, A._asObject(error), type\$.StackTrace._as(stack));\n" +" } else {\n" " t1 = type\$.Object;\n" " t2 = _this.__internal\$_zone;\n" " if (type\$.void_Function_Object_StackTrace._is(handleError))\n" @@ -10770,7 +10634,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " get\$length(_) {\n" " return this._values.length;\n" " },\n" -" get\$__js_helper\$_keys() {\n" +" get\$_keys() {\n" " var keys = this.\$keys;\n" " if (keys == null) {\n" " keys = Object.keys(this._jsIndex);\n" @@ -10793,13 +10657,13 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " forEach\$1(_, f) {\n" " var keys, values, t1, i;\n" " this.\$ti._eval\$1(\"~(1,2)\")._as(f);\n" -" keys = this.get\$__js_helper\$_keys();\n" +" keys = this.get\$_keys();\n" " values = this._values;\n" " for (t1 = keys.length, i = 0; i < t1; ++i)\n" " f.call\$2(keys[i], values[i]);\n" " },\n" " get\$keys() {\n" -" return new A._KeysOrValues(this.get\$__js_helper\$_keys(), this.\$ti._eval\$1(\"_KeysOrValues<1>\"));\n" +" return new A._KeysOrValues(this.get\$_keys(), this.\$ti._eval\$1(\"_KeysOrValues<1>\"));\n" " }\n" " };\n" " A._KeysOrValues.prototype = {\n" @@ -10853,9 +10717,6 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$2(a0, a1) {\n" " return this._genericClosure.call\$1\$2(a0, a1, this.\$ti._rest[0]);\n" " },\n" -" call\$4(a0, a1, a2, a3) {\n" -" return this._genericClosure.call\$1\$4(a0, a1, a2, a3, this.\$ti._rest[0]);\n" -" },\n" " \$signature() {\n" " return A.instantiatedGenericFunctionType(A.closureFunctionType(this._genericClosure), this.\$ti);\n" " }\n" @@ -10996,12 +10857,12 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " containsKey\$1(key) {\n" " var strings, nums;\n" " if (typeof key == \"string\") {\n" -" strings = this.__js_helper\$_strings;\n" +" strings = this._strings;\n" " if (strings == null)\n" " return false;\n" " return strings[key] != null;\n" " } else if (typeof key == \"number\" && (key & 0x3fffffff) === key) {\n" -" nums = this.__js_helper\$_nums;\n" +" nums = this._nums;\n" " if (nums == null)\n" " return false;\n" " return nums[key] != null;\n" @@ -11012,19 +10873,19 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " var rest = this.__js_helper\$_rest;\n" " if (rest == null)\n" " return false;\n" -" return this.internalFindBucketIndex\$2(rest[this.internalComputeHashCode\$1(key)], key) >= 0;\n" +" return this.internalFindBucketIndex\$2(this._getBucket\$2(rest, key), key) >= 0;\n" " },\n" " \$index(_, key) {\n" " var strings, cell, t1, nums, _null = null;\n" " if (typeof key == \"string\") {\n" -" strings = this.__js_helper\$_strings;\n" +" strings = this._strings;\n" " if (strings == null)\n" " return _null;\n" " cell = strings[key];\n" " t1 = cell == null ? _null : cell.hashMapCellValue;\n" " return t1;\n" " } else if (typeof key == \"number\" && (key & 0x3fffffff) === key) {\n" -" nums = this.__js_helper\$_nums;\n" +" nums = this._nums;\n" " if (nums == null)\n" " return _null;\n" " cell = nums[key];\n" @@ -11038,7 +10899,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " rest = this.__js_helper\$_rest;\n" " if (rest == null)\n" " return null;\n" -" bucket = rest[this.internalComputeHashCode\$1(key)];\n" +" bucket = this._getBucket\$2(rest, key);\n" " index = this.internalFindBucketIndex\$2(bucket, key);\n" " if (index < 0)\n" " return null;\n" @@ -11050,11 +10911,11 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t1._precomputed1._as(key);\n" " t1._rest[1]._as(value);\n" " if (typeof key == \"string\") {\n" -" strings = _this.__js_helper\$_strings;\n" -" _this._addHashTableEntry\$3(strings == null ? _this.__js_helper\$_strings = _this._newHashTable\$0() : strings, key, value);\n" +" strings = _this._strings;\n" +" _this._addHashTableEntry\$3(strings == null ? _this._strings = _this._newHashTable\$0() : strings, key, value);\n" " } else if (typeof key == \"number\" && (key & 0x3fffffff) === key) {\n" -" nums = _this.__js_helper\$_nums;\n" -" _this._addHashTableEntry\$3(nums == null ? _this.__js_helper\$_nums = _this._newHashTable\$0() : nums, key, value);\n" +" nums = _this._nums;\n" +" _this._addHashTableEntry\$3(nums == null ? _this._nums = _this._newHashTable\$0() : nums, key, value);\n" " } else\n" " _this.internalSet\$2(key, value);\n" " },\n" @@ -11136,6 +10997,9 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " internalComputeHashCode\$1(key) {\n" " return J.get\$hashCode\$(key) & 1073741823;\n" " },\n" +" _getBucket\$2(table, key) {\n" +" return table[this.internalComputeHashCode\$1(key)];\n" +" },\n" " internalFindBucketIndex\$2(bucket, key) {\n" " var \$length, i;\n" " if (bucket == null)\n" @@ -11289,13 +11153,13 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$2(o, tag) {\n" " return this.getUnknownTag(o, tag);\n" " },\n" -" \$signature: 58\n" +" \$signature: 73\n" " };\n" " A.initHooks_closure1.prototype = {\n" " call\$1(tag) {\n" " return this.prototypeForTag(A._asString(tag));\n" " },\n" -" \$signature: 55\n" +" \$signature: 59\n" " };\n" " A._Record.prototype = {\n" " get\$runtimeType(_) {\n" @@ -11813,7 +11677,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t2 = this.span;\n" " t1.firstChild ? t1.removeChild(t2) : t1.appendChild(t2);\n" " },\n" -" \$signature: 90\n" +" \$signature: 43\n" " };\n" " A._AsyncRun__scheduleImmediateJsOverride_internalCallback.prototype = {\n" " call\$0() {\n" @@ -11834,12 +11698,6 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " else\n" " throw A.wrapException(A.UnsupportedError\$(\"`setTimeout()` not found.\"));\n" " },\n" -" _TimerImpl\$periodic\$2(milliseconds, callback) {\n" -" if (self.setTimeout != null)\n" -" this._handle = self.setInterval(A.convertDartClosureToJS(new A._TimerImpl\$periodic_closure(this, milliseconds, Date.now(), callback), 0), milliseconds);\n" -" else\n" -" throw A.wrapException(A.UnsupportedError\$(\"Periodic timer.\"));\n" -" },\n" " get\$isActive() {\n" " return this._handle != null;\n" " },\n" @@ -11848,10 +11706,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " var t1 = this._handle;\n" " if (t1 == null)\n" " return;\n" -" if (this._once)\n" -" self.clearTimeout(t1);\n" -" else\n" -" self.clearInterval(t1);\n" +" self.clearTimeout(t1);\n" " this._handle = null;\n" " } else\n" " throw A.wrapException(A.UnsupportedError\$(\"Canceling a timer.\"));\n" @@ -11860,29 +11715,11 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " };\n" " A._TimerImpl_internalCallback.prototype = {\n" " call\$0() {\n" -" var t1 = this.\$this;\n" -" t1._handle = null;\n" -" t1._tick = 1;\n" +" this.\$this._handle = null;\n" " this.callback.call\$0();\n" " },\n" " \$signature: 0\n" " };\n" -" A._TimerImpl\$periodic_closure.prototype = {\n" -" call\$0() {\n" -" var duration, _this = this,\n" -" t1 = _this.\$this,\n" -" tick = t1._tick + 1,\n" -" t2 = _this.milliseconds;\n" -" if (t2 > 0) {\n" -" duration = Date.now() - _this.start;\n" -" if (duration > (tick + 1) * t2)\n" -" tick = B.JSInt_methods.\$tdiv(duration, t2);\n" -" }\n" -" t1._tick = tick;\n" -" _this.callback.call\$1(t1);\n" -" },\n" -" \$signature: 1\n" -" };\n" " A._AsyncAwaitCompleter.prototype = {\n" " complete\$1(value) {\n" " var t2, _this = this,\n" @@ -11919,13 +11756,13 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$2(error, stackTrace) {\n" " this.bodyFunction.call\$2(1, new A.ExceptionAndStackTrace(error, type\$.StackTrace._as(stackTrace)));\n" " },\n" -" \$signature: 41\n" +" \$signature: 48\n" " };\n" " A._wrapJsFunctionForAsync_closure.prototype = {\n" " call\$2(errorCode, result) {\n" " this.\$protected(A._asInt(errorCode), result);\n" " },\n" -" \$signature: 43\n" +" \$signature: 55\n" " };\n" " A.AsyncError.prototype = {\n" " toString\$0(_) {\n" @@ -12011,9 +11848,11 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " };\n" " A._FutureListener.prototype = {\n" " matchesErrorTest\$1(asyncError) {\n" +" var t1;\n" " if ((this.state & 15) !== 6)\n" " return true;\n" -" return this.result._zone.runUnary\$2\$2(type\$.bool_Function_Object._as(this.callback), asyncError.error, type\$.bool, type\$.Object);\n" +" t1 = this.result._zone;\n" +" return t1._runUnaryZoned\$2\$3(t1, type\$.bool_Function_Object._as(this.callback), asyncError.error, type\$.bool, type\$.Object);\n" " },\n" " handleError\$1(asyncError) {\n" " var exception, _this = this,\n" @@ -12024,9 +11863,9 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t3 = asyncError.error,\n" " t4 = _this.result._zone;\n" " if (type\$.dynamic_Function_Object_StackTrace._is(errorCallback))\n" -" result = t4.runBinary\$3\$3(errorCallback, t3, asyncError.stackTrace, t1, t2, type\$.StackTrace);\n" +" result = t4._runBinaryZoned\$3\$4(t4, errorCallback, t3, asyncError.stackTrace, t1, t2, type\$.StackTrace);\n" " else\n" -" result = t4.runUnary\$2\$2(type\$.dynamic_Function_Object._as(errorCallback), t3, t1, t2);\n" +" result = t4._runUnaryZoned\$2\$3(t4, type\$.dynamic_Function_Object._as(errorCallback), t3, t1, t2);\n" " try {\n" " t1 = _this.\$ti._eval\$1(\"2/\")._as(result);\n" " return t1;\n" @@ -12042,15 +11881,16 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " };\n" " A._Future.prototype = {\n" " then\$1\$2\$onError(f, onError, \$R) {\n" -" var currentZone, result, t2,\n" +" var currentZone, t2, result,\n" " t1 = this.\$ti;\n" " t1._bind\$1(\$R)._eval\$1(\"1/(2)\")._as(f);\n" " currentZone = \$.Zone__current;\n" -" if (currentZone === B.C__RootZone) {\n" +" if (currentZone === B.Zone_jYP) {\n" " if (onError != null && !type\$.dynamic_Function_Object_StackTrace._is(onError) && !type\$.dynamic_Function_Object._is(onError))\n" " throw A.wrapException(A.ArgumentError\$value(onError, \"onError\", string\$.Error_));\n" " } else {\n" -" f = currentZone.registerUnaryCallback\$2\$1(f, \$R._eval\$1(\"0/\"), t1._precomputed1);\n" +" t2 = t1._precomputed1;\n" +" f = currentZone._registerUnaryCallbackZoned\$2\$2(currentZone, \$R._eval\$1(\"@<0/>\")._bind\$1(t2)._eval\$1(\"1(2)\")._as(f), \$R._eval\$1(\"0/\"), t2);\n" " if (onError != null)\n" " onError = A._registerErrorHandler(onError, currentZone);\n" " }\n" @@ -12072,21 +11912,21 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " },\n" " catchError\$1(onError) {\n" " var t1 = this.\$ti,\n" -" t2 = \$.Zone__current,\n" -" result = new A._Future(t2, t1);\n" -" if (t2 !== B.C__RootZone)\n" -" onError = A._registerErrorHandler(onError, t2);\n" +" resultZone = \$.Zone__current,\n" +" result = new A._Future(resultZone, t1);\n" +" if (resultZone !== B.Zone_jYP)\n" +" onError = A._registerErrorHandler(onError, resultZone);\n" " this._addListener\$1(new A._FutureListener(result, 2, null, onError, t1._eval\$1(\"_FutureListener<1,1>\")));\n" " return result;\n" " },\n" " whenComplete\$1(action) {\n" -" var t1, t2, result;\n" +" var t1, resultZone, result;\n" " type\$.dynamic_Function._as(action);\n" " t1 = this.\$ti;\n" -" t2 = \$.Zone__current;\n" -" result = new A._Future(t2, t1);\n" -" if (t2 !== B.C__RootZone)\n" -" action = t2.registerCallback\$1\$1(action, type\$.dynamic);\n" +" resultZone = \$.Zone__current;\n" +" result = new A._Future(resultZone, t1);\n" +" if (resultZone !== B.Zone_jYP)\n" +" action = resultZone._registerCallbackZoned\$1\$2(resultZone, action, type\$.dynamic);\n" " this._addListener\$1(new A._FutureListener(result, 8, action, null, t1._eval\$1(\"_FutureListener<1,1>\")));\n" " return result;\n" " },\n" @@ -12113,7 +11953,8 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " }\n" " _this._cloneResult\$1(source);\n" " }\n" -" _this._zone.scheduleMicrotask\$1(new A._Future__addListener_closure(_this, listener));\n" +" t1 = _this._zone;\n" +" t1._scheduleMicrotaskZoned\$2(t1, new A._Future__addListener_closure(_this, listener));\n" " }\n" " },\n" " _prependListeners\$1(listeners) {\n" @@ -12141,7 +11982,8 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _this._cloneResult\$1(source);\n" " }\n" " _box_0.listeners = _this._reverseListeners\$1(listeners);\n" -" _this._zone.scheduleMicrotask\$1(new A._Future__prependListeners_closure(_box_0, _this));\n" +" t1 = _this._zone;\n" +" t1._scheduleMicrotaskZoned\$2(t1, new A._Future__prependListeners_closure(_box_0, _this));\n" " }\n" " },\n" " _removeListeners\$0() {\n" @@ -12180,14 +12022,8 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " A._Future__propagateToListeners(_this, listeners);\n" " },\n" " _completeWithResultOf\$1(source) {\n" -" var t1, t2, listeners, _this = this;\n" -" if ((source._state & 16) !== 0) {\n" -" t1 = _this._zone;\n" -" t2 = source._zone;\n" -" t1 = !(t1 === t2 || t1.get\$errorZone() === t2.get\$errorZone());\n" -" } else\n" -" t1 = false;\n" -" if (t1)\n" +" var listeners, _this = this;\n" +" if ((source._state & 16) !== 0 && _this._zone._handleUncaughtErrorFunction != source._zone._handleUncaughtErrorFunction)\n" " return;\n" " listeners = _this._removeListeners\$0();\n" " _this._cloneResult\$1(source);\n" @@ -12213,18 +12049,21 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " this._asyncCompleteWithValue\$1(value);\n" " },\n" " _asyncCompleteWithValue\$1(value) {\n" -" var _this = this;\n" +" var t1, _this = this;\n" " _this.\$ti._precomputed1._as(value);\n" " _this._state ^= 2;\n" -" _this._zone.scheduleMicrotask\$1(new A._Future__asyncCompleteWithValue_closure(_this, value));\n" +" t1 = _this._zone;\n" +" t1._scheduleMicrotaskZoned\$2(t1, new A._Future__asyncCompleteWithValue_closure(_this, value));\n" " },\n" " _chainFuture\$1(value) {\n" " A._Future__chainCoreFuture(this.\$ti._eval\$1(\"Future<1>\")._as(value), this, false);\n" " return;\n" " },\n" " _asyncCompleteErrorObject\$1(error) {\n" +" var t1;\n" " this._state ^= 2;\n" -" this._zone.scheduleMicrotask\$1(new A._Future__asyncCompleteErrorObject_closure(this, error));\n" +" t1 = this._zone;\n" +" t1._scheduleMicrotaskZoned\$2(t1, new A._Future__asyncCompleteErrorObject_closure(this, error));\n" " },\n" " timeout\$2\$onTimeout(timeLimit, onTimeout) {\n" " var t3, _future, _this = this, t1 = {},\n" @@ -12238,7 +12077,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t3 = \$.Zone__current;\n" " _future = new A._Future(t3, t2);\n" " t1.timer = null;\n" -" t1.timer = A.Timer_Timer(timeLimit, new A._Future_timeout_closure(_this, _future, t3, t3.registerCallback\$1\$1(onTimeout, t2._eval\$1(\"1/\"))));\n" +" t1.timer = A.Timer_Timer(timeLimit, new A._Future_timeout_closure(_this, _future, t3, t3._registerCallbackZoned\$1\$2(t3, t2._eval\$1(\"1/()\")._as(onTimeout), t2._eval\$1(\"1/\"))));\n" " _this.then\$1\$2\$onError(new A._Future_timeout_closure0(t1, _this, _future), new A._Future_timeout_closure1(t1, _future), type\$.Null);\n" " return _future;\n" " },\n" @@ -12276,10 +12115,11 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " };\n" " A._Future__propagateToListeners_handleWhenCompleteCallback.prototype = {\n" " call\$0() {\n" -" var e, s, t1, exception, t2, t3, originalSource, joinedResult, _this = this, completeResult = null;\n" +" var e, s, t1, t2, exception, t3, originalSource, joinedResult, _this = this, completeResult = null;\n" " try {\n" " t1 = _this._box_0.listener;\n" -" completeResult = t1.result._zone.run\$1\$1(type\$.dynamic_Function._as(t1.callback), type\$.dynamic);\n" +" t2 = t1.result._zone;\n" +" completeResult = t2._runZoned\$1\$2(t2, type\$.dynamic_Function._as(t1.callback), type\$.dynamic);\n" " } catch (exception) {\n" " e = A.unwrapException(exception);\n" " s = A.getTraceFromException(exception);\n" @@ -12333,14 +12173,15 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " };\n" " A._Future__propagateToListeners_handleValueCallback.prototype = {\n" " call\$0() {\n" -" var e, s, t1, t2, t3, t4, t5, exception;\n" +" var e, s, t1, t2, t3, t4, t5, t6, exception;\n" " try {\n" " t1 = this._box_0;\n" " t2 = t1.listener;\n" " t3 = t2.\$ti;\n" " t4 = t3._precomputed1;\n" " t5 = t4._as(this.sourceResult);\n" -" t1.listenerValueOrError = t2.result._zone.runUnary\$2\$2(t3._eval\$1(\"2/(1)\")._as(t2.callback), t5, t3._eval\$1(\"2/\"), t4);\n" +" t6 = t2.result._zone;\n" +" t1.listenerValueOrError = t6._runUnaryZoned\$2\$3(t6, t3._eval\$1(\"2/(1)\")._as(t2.callback), t5, t3._eval\$1(\"2/\"), t4);\n" " } catch (exception) {\n" " e = A.unwrapException(exception);\n" " s = A.getTraceFromException(exception);\n" @@ -12389,9 +12230,11 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " };\n" " A._Future_timeout_closure.prototype = {\n" " call\$0() {\n" -" var e, s, exception, t1, t2, _this = this;\n" +" var e, s, t1, t2, exception, _this = this;\n" " try {\n" -" _this._future._complete\$1(_this.zone.run\$1\$1(_this.onTimeoutHandler, _this.\$this.\$ti._eval\$1(\"1/\")));\n" +" t1 = _this.zone;\n" +" t2 = _this.\$this.\$ti;\n" +" _this._future._complete\$1(t1._runZoned\$1\$2(t1, t2._eval\$1(\"1/()\")._as(_this.onTimeoutHandler), t2._eval\$1(\"1/\")));\n" " } catch (exception) {\n" " e = A.unwrapException(exception);\n" " s = A.getTraceFromException(exception);\n" @@ -12578,7 +12421,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t5 = A._BufferingStreamSubscription__registerDataHandler(t2, onData, t1._precomputed1);\n" " t6 = A._BufferingStreamSubscription__registerErrorHandler(t2, onError);\n" " t7 = onDone == null ? A.async___nullDoneHandler\$closure() : onDone;\n" -" subscription = new A._ControllerSubscription(_this, t5, t6, t2.registerCallback\$1\$1(t7, type\$.void), t2, t3 | t4, t1._eval\$1(\"_ControllerSubscription<1>\"));\n" +" subscription = new A._ControllerSubscription(_this, t5, t6, t2._registerCallbackZoned\$1\$2(t2, type\$.void_Function._as(t7), type\$.void), t2, t3 | t4, t1._eval\$1(\"_ControllerSubscription<1>\"));\n" " pendingEvents = _this.get\$_pendingEvents();\n" " if (((_this._state |= 1) & 8) !== 0) {\n" " addState = t1._eval\$1(\"_StreamControllerAddStreamState<1>\")._as(_this._varData);\n" @@ -13154,7 +12997,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t1 = new A._DoneStreamSubscription(t2, t1._eval\$1(\"_DoneStreamSubscription<1>\"));\n" " A.scheduleMicrotask(t1.get\$_onMicrotask());\n" " if (onDone != null)\n" -" t1._onDone = t2.registerCallback\$1\$1(onDone, type\$.void);\n" +" t1._onDone = t2._registerCallbackZoned\$1\$2(t2, type\$.void_Function._as(onDone), type\$.void);\n" " return t1;\n" " },\n" " listen\$3\$onDone\$onError(onData, onDone, onError) {\n" @@ -13220,7 +13063,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t5 = A._BufferingStreamSubscription__registerDataHandler(t2, onData, t1._rest[1]);\n" " t6 = A._BufferingStreamSubscription__registerErrorHandler(t2, onError);\n" " t7 = onDone == null ? A.async___nullDoneHandler\$closure() : onDone;\n" -" t1 = new A._ForwardingStreamSubscription(this, t5, t6, t2.registerCallback\$1\$1(t7, type\$.void), t2, t3 | t4, t1._eval\$1(\"_ForwardingStreamSubscription<1,2>\"));\n" +" t1 = new A._ForwardingStreamSubscription(this, t5, t6, t2._registerCallbackZoned\$1\$2(t2, type\$.void_Function._as(t7), type\$.void), t2, t3 | t4, t1._eval\$1(\"_ForwardingStreamSubscription<1,2>\"));\n" " t1._subscription = this._source.listen\$3\$onDone\$onError(t1.get\$_handleData(), t1.get\$_handleDone(), t1.get\$_handleError());\n" " return t1;\n" " },\n" @@ -13302,480 +13145,276 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " sink._add\$1(outputEvent);\n" " }\n" " };\n" -" A._ZoneFunction.prototype = {};\n" -" A._Zone.prototype = {\n" -" _processUncaughtError\$3(zone, error, stackTrace) {\n" -" var implZone, handler, parentDelegate, parentZone, currentZone, e, s, implementation, t1, exception;\n" -" type\$.StackTrace._as(stackTrace);\n" -" implementation = this.get\$_handleUncaughtError();\n" -" implZone = implementation.zone;\n" -" if (implZone === B.C__RootZone) {\n" -" A._rootHandleError(error, stackTrace);\n" -" return;\n" -" }\n" -" handler = implementation.\$function;\n" -" parentDelegate = implZone.get\$_parentDelegate();\n" -" t1 = implZone.get\$parent();\n" -" t1.toString;\n" -" parentZone = t1;\n" -" currentZone = \$.Zone__current;\n" -" try {\n" -" \$.Zone__current = parentZone;\n" -" handler.call\$5(implZone, parentDelegate, zone, error, stackTrace);\n" -" \$.Zone__current = currentZone;\n" -" } catch (exception) {\n" -" e = A.unwrapException(exception);\n" -" s = A.getTraceFromException(exception);\n" -" \$.Zone__current = currentZone;\n" -" t1 = error === e ? stackTrace : s;\n" -" parentZone._processUncaughtError\$3(implZone, e, t1);\n" -" }\n" -" },\n" -" \$isZone: 1\n" -" };\n" -" A._CustomZone.prototype = {\n" -" get\$_delegate() {\n" -" var t1 = this._delegateCache;\n" -" return t1 == null ? this._delegateCache = new A._ZoneDelegate(this) : t1;\n" -" },\n" -" get\$_parentDelegate() {\n" -" return this.parent.get\$_delegate();\n" -" },\n" -" get\$errorZone() {\n" -" return this._handleUncaughtError.zone;\n" +" A._ZoneHandleUncaughtError.prototype = {};\n" +" A.Zone.prototype = {\n" +" run\$1\$1(action, \$R) {\n" +" return this._runZoned\$1\$2(this, \$R._eval\$1(\"0()\")._as(action), \$R);\n" " },\n" -" runGuarded\$1(f) {\n" -" var e, s, exception;\n" -" type\$.void_Function._as(f);\n" +" runGuarded\$1(action) {\n" +" var e, s, t1, exception, _this = this;\n" +" type\$.void_Function._as(action);\n" " try {\n" -" this.run\$1\$1(f, type\$.void);\n" +" t1 = _this._runZoned\$1\$2(_this, action, type\$.void);\n" +" return t1;\n" " } catch (exception) {\n" " e = A.unwrapException(exception);\n" " s = A.getTraceFromException(exception);\n" -" this._processUncaughtError\$3(this, A._asObject(e), type\$.StackTrace._as(s));\n" +" _this._handleUncaughtErrorZoned\$3(_this, e, s);\n" " }\n" " },\n" -" runUnaryGuarded\$1\$2(f, arg, \$T) {\n" -" var e, s, exception;\n" -" \$T._eval\$1(\"~(0)\")._as(f);\n" -" \$T._as(arg);\n" +" runUnaryGuarded\$1\$2(action, argument, \$T) {\n" +" var e, s, t1, exception, _this = this;\n" +" \$T._eval\$1(\"~(0)\")._as(action);\n" +" \$T._as(argument);\n" " try {\n" -" this.runUnary\$2\$2(f, arg, type\$.void, \$T);\n" +" t1 = _this._runUnaryZoned\$2\$3(_this, action, argument, type\$.void, \$T);\n" +" return t1;\n" " } catch (exception) {\n" " e = A.unwrapException(exception);\n" " s = A.getTraceFromException(exception);\n" -" this._processUncaughtError\$3(this, A._asObject(e), type\$.StackTrace._as(s));\n" +" _this._handleUncaughtErrorZoned\$3(_this, e, s);\n" " }\n" " },\n" -" runBinaryGuarded\$2\$3(f, arg1, arg2, \$T1, \$T2) {\n" -" var e, s, exception;\n" -" \$T1._eval\$1(\"@<0>\")._bind\$1(\$T2)._eval\$1(\"~(1,2)\")._as(f);\n" -" \$T1._as(arg1);\n" -" \$T2._as(arg2);\n" +" runBinaryGuarded\$2\$3(action, argument1, argument2, \$T1, \$T2) {\n" +" var e, s, t1, exception, _this = this;\n" +" \$T1._eval\$1(\"@<0>\")._bind\$1(\$T2)._eval\$1(\"~(1,2)\")._as(action);\n" +" \$T1._as(argument1);\n" +" \$T2._as(argument2);\n" " try {\n" -" this.runBinary\$3\$3(f, arg1, arg2, type\$.void, \$T1, \$T2);\n" +" t1 = _this._runBinaryZoned\$3\$4(_this, action, argument1, argument2, type\$.void, \$T1, \$T2);\n" +" return t1;\n" " } catch (exception) {\n" " e = A.unwrapException(exception);\n" " s = A.getTraceFromException(exception);\n" -" this._processUncaughtError\$3(this, A._asObject(e), type\$.StackTrace._as(s));\n" -" }\n" -" },\n" -" bindCallback\$1\$1(f, \$R) {\n" -" return new A._CustomZone_bindCallback_closure(this, this.registerCallback\$1\$1(\$R._eval\$1(\"0()\")._as(f), \$R), \$R);\n" -" },\n" -" bindUnaryCallback\$2\$1(f, \$R, \$T) {\n" -" return new A._CustomZone_bindUnaryCallback_closure(this, this.registerUnaryCallback\$2\$1(\$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(f), \$R, \$T), \$T, \$R);\n" -" },\n" -" bindCallbackGuarded\$1(f) {\n" -" return new A._CustomZone_bindCallbackGuarded_closure(this, this.registerCallback\$1\$1(type\$.void_Function._as(f), type\$.void));\n" -" },\n" -" bindUnaryCallbackGuarded\$1\$1(f, \$T) {\n" -" return new A._CustomZone_bindUnaryCallbackGuarded_closure(this, this.registerUnaryCallback\$2\$1(\$T._eval\$1(\"~(0)\")._as(f), type\$.void, \$T), \$T);\n" -" },\n" -" handleUncaughtError\$2(error, stackTrace) {\n" -" this._processUncaughtError\$3(this, error, type\$.StackTrace._as(stackTrace));\n" -" },\n" -" fork\$2\$specification\$zoneValues(specification, zoneValues) {\n" -" var implementation = this._fork,\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$5(t1, t1.get\$_parentDelegate(), this, specification, zoneValues);\n" -" },\n" -" run\$1\$1(f, \$R) {\n" -" var implementation, t1;\n" -" \$R._eval\$1(\"0()\")._as(f);\n" -" implementation = this._run;\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$1\$4(t1, t1.get\$_parentDelegate(), this, f, \$R);\n" -" },\n" -" runUnary\$2\$2(f, arg, \$R, \$T) {\n" -" var implementation, t1;\n" -" \$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(f);\n" -" \$T._as(arg);\n" -" implementation = this._runUnary;\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$2\$5(t1, t1.get\$_parentDelegate(), this, f, arg, \$R, \$T);\n" -" },\n" -" runBinary\$3\$3(f, arg1, arg2, \$R, \$T1, \$T2) {\n" -" var implementation, t1;\n" -" \$R._eval\$1(\"@<0>\")._bind\$1(\$T1)._bind\$1(\$T2)._eval\$1(\"1(2,3)\")._as(f);\n" -" \$T1._as(arg1);\n" -" \$T2._as(arg2);\n" -" implementation = this._runBinary;\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$3\$6(t1, t1.get\$_parentDelegate(), this, f, arg1, arg2, \$R, \$T1, \$T2);\n" -" },\n" -" registerCallback\$1\$1(callback, \$R) {\n" -" var implementation, t1;\n" -" \$R._eval\$1(\"0()\")._as(callback);\n" -" implementation = this._registerCallback;\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$1\$4(t1, t1.get\$_parentDelegate(), this, callback, \$R);\n" -" },\n" -" registerUnaryCallback\$2\$1(callback, \$R, \$T) {\n" -" var implementation, t1;\n" -" \$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(callback);\n" -" implementation = this._registerUnaryCallback;\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$2\$4(t1, t1.get\$_parentDelegate(), this, callback, \$R, \$T);\n" -" },\n" -" registerBinaryCallback\$3\$1(callback, \$R, \$T1, \$T2) {\n" -" var implementation, t1;\n" -" \$R._eval\$1(\"@<0>\")._bind\$1(\$T1)._bind\$1(\$T2)._eval\$1(\"1(2,3)\")._as(callback);\n" -" implementation = this._registerBinaryCallback;\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$3\$4(t1, t1.get\$_parentDelegate(), this, callback, \$R, \$T1, \$T2);\n" -" },\n" -" errorCallback\$2(error, stackTrace) {\n" -" var implementation = this._errorCallback,\n" -" implementationZone = implementation.zone;\n" -" if (implementationZone === B.C__RootZone)\n" -" return null;\n" -" return implementation.\$function.call\$5(implementationZone, implementationZone.get\$_parentDelegate(), this, error, stackTrace);\n" -" },\n" -" scheduleMicrotask\$1(f) {\n" -" var implementation, t1;\n" -" type\$.void_Function._as(f);\n" -" implementation = this._scheduleMicrotask;\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$4(t1, t1.get\$_parentDelegate(), this, f);\n" -" },\n" -" createTimer\$2(duration, f) {\n" -" var implementation, t1;\n" -" type\$.void_Function._as(f);\n" -" implementation = this._createTimer;\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$5(t1, t1.get\$_parentDelegate(), this, duration, f);\n" -" },\n" -" print\$1(line) {\n" -" var implementation = this._print,\n" -" t1 = implementation.zone;\n" -" return implementation.\$function.call\$4(t1, t1.get\$_parentDelegate(), this, line);\n" -" },\n" -" get\$_run() {\n" -" return this._run;\n" -" },\n" -" get\$_runUnary() {\n" -" return this._runUnary;\n" -" },\n" -" get\$_runBinary() {\n" -" return this._runBinary;\n" -" },\n" -" get\$_registerCallback() {\n" -" return this._registerCallback;\n" -" },\n" -" get\$_registerUnaryCallback() {\n" -" return this._registerUnaryCallback;\n" -" },\n" -" get\$_registerBinaryCallback() {\n" -" return this._registerBinaryCallback;\n" -" },\n" -" get\$_errorCallback() {\n" -" return this._errorCallback;\n" -" },\n" -" get\$_scheduleMicrotask() {\n" -" return this._scheduleMicrotask;\n" -" },\n" -" get\$_createTimer() {\n" -" return this._createTimer;\n" -" },\n" -" get\$_createPeriodicTimer() {\n" -" return this._createPeriodicTimer;\n" -" },\n" -" get\$_print() {\n" -" return this._print;\n" -" },\n" -" get\$_fork() {\n" -" return this._fork;\n" -" },\n" -" get\$_handleUncaughtError() {\n" -" return this._handleUncaughtError;\n" -" },\n" -" get\$parent() {\n" -" return this.parent;\n" -" },\n" -" get\$_map() {\n" -" return this._map;\n" -" }\n" -" };\n" -" A._CustomZone_bindCallback_closure.prototype = {\n" -" call\$0() {\n" -" return this.\$this.run\$1\$1(this.registered, this.R);\n" -" },\n" -" \$signature() {\n" -" return this.R._eval\$1(\"0()\");\n" -" }\n" -" };\n" -" A._CustomZone_bindUnaryCallback_closure.prototype = {\n" -" call\$1(arg) {\n" -" var _this = this,\n" -" t1 = _this.T;\n" -" return _this.\$this.runUnary\$2\$2(_this.registered, t1._as(arg), _this.R, t1);\n" -" },\n" -" \$signature() {\n" -" return this.R._eval\$1(\"@<0>\")._bind\$1(this.T)._eval\$1(\"1(2)\");\n" -" }\n" -" };\n" -" A._CustomZone_bindCallbackGuarded_closure.prototype = {\n" -" call\$0() {\n" -" return this.\$this.runGuarded\$1(this.registered);\n" -" },\n" -" \$signature: 0\n" -" };\n" -" A._CustomZone_bindUnaryCallbackGuarded_closure.prototype = {\n" -" call\$1(arg) {\n" -" var t1 = this.T;\n" -" return this.\$this.runUnaryGuarded\$1\$2(this.registered, t1._as(arg), t1);\n" -" },\n" -" \$signature() {\n" -" return this.T._eval\$1(\"~(0)\");\n" -" }\n" -" };\n" -" A._RootZone.prototype = {\n" -" get\$_run() {\n" -" return B._ZoneFunction__RootZone__rootRun;\n" -" },\n" -" get\$_runUnary() {\n" -" return B._ZoneFunction__RootZone__rootRunUnary;\n" -" },\n" -" get\$_runBinary() {\n" -" return B._ZoneFunction__RootZone__rootRunBinary;\n" -" },\n" -" get\$_registerCallback() {\n" -" return B._ZoneFunction__RootZone__rootRegisterCallback;\n" -" },\n" -" get\$_registerUnaryCallback() {\n" -" return B._ZoneFunction_Xkh;\n" -" },\n" -" get\$_registerBinaryCallback() {\n" -" return B._ZoneFunction_e9o;\n" -" },\n" -" get\$_errorCallback() {\n" -" return B._ZoneFunction__RootZone__rootErrorCallback;\n" -" },\n" -" get\$_scheduleMicrotask() {\n" -" return B._ZoneFunction__RootZone__rootScheduleMicrotask;\n" -" },\n" -" get\$_createTimer() {\n" -" return B._ZoneFunction__RootZone__rootCreateTimer;\n" -" },\n" -" get\$_createPeriodicTimer() {\n" -" return B._ZoneFunction_PAY;\n" -" },\n" -" get\$_print() {\n" -" return B._ZoneFunction__RootZone__rootPrint;\n" -" },\n" -" get\$_fork() {\n" -" return B._ZoneFunction__RootZone__rootFork;\n" -" },\n" -" get\$_handleUncaughtError() {\n" -" return B._ZoneFunction_KjJ;\n" +" _this._handleUncaughtErrorZoned\$3(_this, e, s);\n" +" }\n" " },\n" -" get\$parent() {\n" -" return null;\n" +" bindCallback\$1\$1(callback, \$R) {\n" +" return new A.Zone_bindCallback_closure(this, this._registerCallbackZoned\$1\$2(this, \$R._eval\$1(\"0()\")._as(callback), \$R), \$R);\n" " },\n" -" get\$_map() {\n" -" return \$.\$get\$_RootZone__rootMap();\n" +" bindCallbackGuarded\$1(callback) {\n" +" return new A.Zone_bindCallbackGuarded_closure(this, this._registerCallbackZoned\$1\$2(this, type\$.void_Function._as(callback), type\$.void));\n" " },\n" -" get\$_delegate() {\n" -" var t1 = \$._RootZone__rootDelegate;\n" -" return t1 == null ? \$._RootZone__rootDelegate = new A._ZoneDelegate(this) : t1;\n" +" bindUnaryCallbackGuarded\$1\$1(callback, \$T) {\n" +" return new A.Zone_bindUnaryCallbackGuarded_closure(this, this._registerUnaryCallbackZoned\$2\$2(this, \$T._eval\$1(\"~(0)\")._as(callback), type\$.void, \$T), \$T);\n" " },\n" " get\$_parentDelegate() {\n" -" var t1 = \$._RootZone__rootDelegate;\n" -" return t1 == null ? \$._RootZone__rootDelegate = new A._ZoneDelegate(this) : t1;\n" -" },\n" -" get\$errorZone() {\n" -" return this;\n" +" var t1 = this._parent;\n" +" t1 = t1 == null ? null : t1._delegate;\n" +" return t1 == null ? \$.\$get\$_rootDelegate() : t1;\n" " },\n" -" runGuarded\$1(f) {\n" -" var e, s, exception;\n" -" type\$.void_Function._as(f);\n" +" _handleUncaughtErrorZoned\$3(zone, error, stackTrace) {\n" +" var implementation, implZone, parentZone, currentZone, e, s, t1, exception;\n" +" type\$.StackTrace._as(stackTrace);\n" +" implementation = this._handleUncaughtErrorFunction;\n" +" if (implementation == null) {\n" +" A._rootHandleUncaughtError(error, stackTrace);\n" +" return;\n" +" }\n" +" implZone = implementation.zone;\n" +" t1 = implZone._parent;\n" +" t1.toString;\n" +" parentZone = t1;\n" +" currentZone = \$.Zone__current;\n" " try {\n" -" if (B.C__RootZone === \$.Zone__current) {\n" -" f.call\$0();\n" -" return;\n" -" }\n" -" A._rootRun(null, null, this, f, type\$.void);\n" +" \$.Zone__current = parentZone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" implementation.\$function.call\$5(implZone, t1, zone, error, stackTrace);\n" +" \$.Zone__current = currentZone;\n" " } catch (exception) {\n" " e = A.unwrapException(exception);\n" " s = A.getTraceFromException(exception);\n" -" A._rootHandleError(A._asObject(e), type\$.StackTrace._as(s));\n" +" \$.Zone__current = currentZone;\n" +" t1 = error === e ? stackTrace : s;\n" +" parentZone._handleUncaughtErrorZoned\$3(implZone, e, t1);\n" " }\n" " },\n" -" runUnaryGuarded\$1\$2(f, arg, \$T) {\n" -" var e, s, exception;\n" -" \$T._eval\$1(\"~(0)\")._as(f);\n" -" \$T._as(arg);\n" -" try {\n" -" if (B.C__RootZone === \$.Zone__current) {\n" -" f.call\$1(arg);\n" -" return;\n" +" _forkZoned\$3(zone, specification, zoneValues) {\n" +" var implZone, t1,\n" +" implementation = this._forkFunction;\n" +" if (implementation == null)\n" +" return A._rootFork(zone, specification, zoneValues);\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" return implementation.\$function.call\$5(implZone, t1, zone, specification, zoneValues);\n" +" },\n" +" _runZoned\$1\$2(zone, callback, \$R) {\n" +" var oldZone, implementation, t1, implZone;\n" +" \$R._eval\$1(\"0()\")._as(callback);\n" +" implementation = this._runFunction;\n" +" if (implementation == null) {\n" +" t1 = \$.Zone__current;\n" +" if (t1 === zone)\n" +" return callback.call\$0();\n" +" oldZone = t1;\n" +" \$.Zone__current = zone;\n" +" try {\n" +" t1 = callback.call\$0();\n" +" return t1;\n" +" } finally {\n" +" \$.Zone__current = oldZone;\n" " }\n" -" A._rootRunUnary(null, null, this, f, arg, type\$.void, \$T);\n" -" } catch (exception) {\n" -" e = A.unwrapException(exception);\n" -" s = A.getTraceFromException(exception);\n" -" A._rootHandleError(A._asObject(e), type\$.StackTrace._as(s));\n" " }\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" return implementation.\$function.call\$1\$4(implZone, t1, zone, callback, \$R);\n" " },\n" -" runBinaryGuarded\$2\$3(f, arg1, arg2, \$T1, \$T2) {\n" -" var e, s, exception;\n" -" \$T1._eval\$1(\"@<0>\")._bind\$1(\$T2)._eval\$1(\"~(1,2)\")._as(f);\n" -" \$T1._as(arg1);\n" -" \$T2._as(arg2);\n" -" try {\n" -" if (B.C__RootZone === \$.Zone__current) {\n" -" f.call\$2(arg1, arg2);\n" -" return;\n" +" _runUnaryZoned\$2\$3(zone, callback, argument, \$R, \$T) {\n" +" var oldZone, implementation, t1, implZone;\n" +" \$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(callback);\n" +" \$T._as(argument);\n" +" implementation = this._runUnaryFunction;\n" +" if (implementation == null) {\n" +" t1 = \$.Zone__current;\n" +" if (t1 === zone)\n" +" return callback.call\$1(argument);\n" +" oldZone = t1;\n" +" \$.Zone__current = zone;\n" +" try {\n" +" t1 = callback.call\$1(argument);\n" +" return t1;\n" +" } finally {\n" +" \$.Zone__current = oldZone;\n" " }\n" -" A._rootRunBinary(null, null, this, f, arg1, arg2, type\$.void, \$T1, \$T2);\n" -" } catch (exception) {\n" -" e = A.unwrapException(exception);\n" -" s = A.getTraceFromException(exception);\n" -" A._rootHandleError(A._asObject(e), type\$.StackTrace._as(s));\n" " }\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" return implementation.\$function.call\$2\$5(implZone, t1, zone, callback, argument, \$R, \$T);\n" " },\n" -" bindCallback\$1\$1(f, \$R) {\n" -" return new A._RootZone_bindCallback_closure(this, \$R._eval\$1(\"0()\")._as(f), \$R);\n" -" },\n" -" bindUnaryCallback\$2\$1(f, \$R, \$T) {\n" -" return new A._RootZone_bindUnaryCallback_closure(this, \$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(f), \$T, \$R);\n" -" },\n" -" bindCallbackGuarded\$1(f) {\n" -" return new A._RootZone_bindCallbackGuarded_closure(this, type\$.void_Function._as(f));\n" -" },\n" -" bindUnaryCallbackGuarded\$1\$1(f, \$T) {\n" -" return new A._RootZone_bindUnaryCallbackGuarded_closure(this, \$T._eval\$1(\"~(0)\")._as(f), \$T);\n" -" },\n" -" handleUncaughtError\$2(error, stackTrace) {\n" -" A._rootHandleError(error, type\$.StackTrace._as(stackTrace));\n" -" },\n" -" fork\$2\$specification\$zoneValues(specification, zoneValues) {\n" -" return A._rootFork(null, null, this, specification, zoneValues);\n" -" },\n" -" run\$1\$1(f, \$R) {\n" -" \$R._eval\$1(\"0()\")._as(f);\n" -" if (\$.Zone__current === B.C__RootZone)\n" -" return f.call\$0();\n" -" return A._rootRun(null, null, this, f, \$R);\n" -" },\n" -" runUnary\$2\$2(f, arg, \$R, \$T) {\n" -" \$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(f);\n" -" \$T._as(arg);\n" -" if (\$.Zone__current === B.C__RootZone)\n" -" return f.call\$1(arg);\n" -" return A._rootRunUnary(null, null, this, f, arg, \$R, \$T);\n" -" },\n" -" runBinary\$3\$3(f, arg1, arg2, \$R, \$T1, \$T2) {\n" -" \$R._eval\$1(\"@<0>\")._bind\$1(\$T1)._bind\$1(\$T2)._eval\$1(\"1(2,3)\")._as(f);\n" -" \$T1._as(arg1);\n" -" \$T2._as(arg2);\n" -" if (\$.Zone__current === B.C__RootZone)\n" -" return f.call\$2(arg1, arg2);\n" -" return A._rootRunBinary(null, null, this, f, arg1, arg2, \$R, \$T1, \$T2);\n" -" },\n" -" registerCallback\$1\$1(f, \$R) {\n" -" return \$R._eval\$1(\"0()\")._as(f);\n" +" _runBinaryZoned\$3\$4(zone, callback, argument1, argument2, \$R, \$T1, \$T2) {\n" +" var oldZone, implementation, t1, implZone;\n" +" \$R._eval\$1(\"@<0>\")._bind\$1(\$T1)._bind\$1(\$T2)._eval\$1(\"1(2,3)\")._as(callback);\n" +" \$T1._as(argument1);\n" +" \$T2._as(argument2);\n" +" implementation = this._runBinaryFunction;\n" +" if (implementation == null) {\n" +" t1 = \$.Zone__current;\n" +" if (t1 === zone)\n" +" return callback.call\$2(argument1, argument2);\n" +" oldZone = t1;\n" +" \$.Zone__current = zone;\n" +" try {\n" +" t1 = callback.call\$2(argument1, argument2);\n" +" return t1;\n" +" } finally {\n" +" \$.Zone__current = oldZone;\n" +" }\n" +" }\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" return implementation.\$function.call\$3\$6(implZone, t1, zone, callback, argument1, argument2, \$R, \$T1, \$T2);\n" " },\n" -" registerUnaryCallback\$2\$1(f, \$R, \$T) {\n" -" return \$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(f);\n" +" _registerCallbackZoned\$1\$2(zone, callback, \$R) {\n" +" var implementation, implZone, t1;\n" +" \$R._eval\$1(\"0()\")._as(callback);\n" +" implementation = this._registerCallbackFunction;\n" +" if (implementation == null)\n" +" return callback;\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" return implementation.\$function.call\$1\$4(implZone, t1, zone, callback, \$R);\n" " },\n" -" registerBinaryCallback\$3\$1(f, \$R, \$T1, \$T2) {\n" -" return \$R._eval\$1(\"@<0>\")._bind\$1(\$T1)._bind\$1(\$T2)._eval\$1(\"1(2,3)\")._as(f);\n" +" _registerUnaryCallbackZoned\$2\$2(zone, callback, \$R, \$T) {\n" +" var implementation, implZone, t1;\n" +" \$R._eval\$1(\"@<0>\")._bind\$1(\$T)._eval\$1(\"1(2)\")._as(callback);\n" +" implementation = this._registerUnaryCallbackFunction;\n" +" if (implementation == null)\n" +" return callback;\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" return implementation.\$function.call\$2\$4(implZone, t1, zone, callback, \$R, \$T);\n" " },\n" -" errorCallback\$2(error, stackTrace) {\n" -" return null;\n" +" _registerBinaryCallbackZoned\$3\$2(zone, callback, \$R, \$T1, \$T2) {\n" +" var implementation, implZone, t1;\n" +" \$R._eval\$1(\"@<0>\")._bind\$1(\$T1)._bind\$1(\$T2)._eval\$1(\"1(2,3)\")._as(callback);\n" +" implementation = this._registerBinaryCallbackFunction;\n" +" if (implementation == null)\n" +" return callback;\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" return implementation.\$function.call\$3\$4(implZone, t1, zone, callback, \$R, \$T1, \$T2);\n" " },\n" -" scheduleMicrotask\$1(f) {\n" -" A._rootScheduleMicrotask(null, null, this, type\$.void_Function._as(f));\n" +" _errorCallbackZoned\$3(zone, error, stackTrace) {\n" +" var implZone, t1,\n" +" implementation = this._errorCallbackFunction;\n" +" if (implementation == null)\n" +" return null;\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" return implementation.\$function.call\$5(implZone, t1, zone, error, stackTrace);\n" " },\n" -" createTimer\$2(duration, f) {\n" -" return A.Timer__createTimer(duration, type\$.void_Function._as(f));\n" +" _scheduleMicrotaskZoned\$2(zone, callback) {\n" +" var implementation, implZone, t1;\n" +" type\$.void_Function._as(callback);\n" +" implementation = this._scheduleMicrotaskFunction;\n" +" if (implementation == null) {\n" +" A._rootScheduleMicrotask(zone, callback);\n" +" return;\n" +" }\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" implementation.\$function.call\$4(implZone, t1, zone, callback);\n" " },\n" -" print\$1(line) {\n" -" A.printString(line);\n" +" _createTimerZoned\$3(zone, duration, callback) {\n" +" var implementation, implZone, t1;\n" +" type\$.void_Function._as(callback);\n" +" implementation = this._createTimerFunction;\n" +" if (implementation == null)\n" +" return A.Timer__createTimer(duration, B.Zone_jYP !== zone ? zone.bindCallback\$1\$1(callback, type\$.void) : callback);\n" +" implZone = implementation.zone;\n" +" t1 = implZone.get\$_parentDelegate();\n" +" return implementation.\$function.call\$5(implZone, t1, zone, duration, callback);\n" " }\n" " };\n" -" A._RootZone_bindCallback_closure.prototype = {\n" +" A.Zone_bindCallback_closure.prototype = {\n" " call\$0() {\n" -" return this.\$this.run\$1\$1(this.f, this.R);\n" +" var t1 = this.\$this;\n" +" return t1._runZoned\$1\$2(t1, this.registered, this.R);\n" " },\n" " \$signature() {\n" " return this.R._eval\$1(\"0()\");\n" " }\n" " };\n" -" A._RootZone_bindUnaryCallback_closure.prototype = {\n" -" call\$1(arg) {\n" -" var _this = this,\n" -" t1 = _this.T;\n" -" return _this.\$this.runUnary\$2\$2(_this.f, t1._as(arg), _this.R, t1);\n" -" },\n" -" \$signature() {\n" -" return this.R._eval\$1(\"@<0>\")._bind\$1(this.T)._eval\$1(\"1(2)\");\n" -" }\n" -" };\n" -" A._RootZone_bindCallbackGuarded_closure.prototype = {\n" +" A.Zone_bindCallbackGuarded_closure.prototype = {\n" " call\$0() {\n" -" return this.\$this.runGuarded\$1(this.f);\n" +" return this.\$this.runGuarded\$1(this.registered);\n" " },\n" " \$signature: 0\n" " };\n" -" A._RootZone_bindUnaryCallbackGuarded_closure.prototype = {\n" -" call\$1(arg) {\n" +" A.Zone_bindUnaryCallbackGuarded_closure.prototype = {\n" +" call\$1(argument) {\n" " var t1 = this.T;\n" -" return this.\$this.runUnaryGuarded\$1\$2(this.f, t1._as(arg), t1);\n" +" return this.\$this.runUnaryGuarded\$1\$2(this.registered, t1._as(argument), t1);\n" " },\n" " \$signature() {\n" " return this.T._eval\$1(\"~(0)\");\n" " }\n" " };\n" -" A.runZonedGuarded_closure.prototype = {\n" +" A.runZonedGuarded_errorHandler.prototype = {\n" " call\$5(\$self, \$parent, zone, error, stackTrace) {\n" -" var e, s, exception, t2,\n" -" t1 = type\$.StackTrace;\n" -" t1._as(stackTrace);\n" +" var e, s, t1, exception, t2;\n" " try {\n" -" this.parentZone.runBinary\$3\$3(this.onError, error, stackTrace, type\$.void, type\$.Object, t1);\n" +" t1 = this.parentZone;\n" +" t1._runBinaryZoned\$3\$4(t1, type\$.void_Function_Object_StackTrace._as(this.onError), error, stackTrace, type\$.void, type\$.Object, type\$.StackTrace);\n" " } catch (exception) {\n" " e = A.unwrapException(exception);\n" " s = A.getTraceFromException(exception);\n" -" t2 = \$parent._delegationTarget;\n" -" if (e === error)\n" -" t2._processUncaughtError\$3(zone, error, stackTrace);\n" -" else\n" -" t2._processUncaughtError\$3(zone, A._asObject(e), t1._as(s));\n" +" t1 = e === error ? stackTrace : s;\n" +" t2 = A._asObject(e);\n" +" type\$.StackTrace._as(t1);\n" +" \$parent._zone._handleUncaughtErrorZoned\$3(zone, t2, t1);\n" " }\n" " },\n" -" \$signature: 31\n" +" \$signature: 32\n" " };\n" -" A._ZoneDelegate.prototype = {\$isZoneDelegate: 1};\n" -" A._rootHandleError_closure.prototype = {\n" +" A.ZoneDelegate.prototype = {};\n" +" A._rootHandleUncaughtError_closure.prototype = {\n" " call\$0() {\n" " A.Error_throwWithStackTrace(this.error, this.stackTrace);\n" " },\n" " \$signature: 0\n" " };\n" -" A._ZoneSpecification.prototype = {\$isZoneSpecification: 1};\n" +" A.ZoneSpecification.prototype = {};\n" " A._HashMap.prototype = {\n" " get\$length(_) {\n" " return this._collection\$_length;\n" @@ -13792,10 +13431,10 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " containsKey\$1(key) {\n" " var strings, nums;\n" " if (typeof key == \"string\" && key !== \"__proto__\") {\n" -" strings = this._strings;\n" +" strings = this._collection\$_strings;\n" " return strings == null ? false : strings[key] != null;\n" " } else if (typeof key == \"number\" && (key & 1073741823) === key) {\n" -" nums = this._nums;\n" +" nums = this._collection\$_nums;\n" " return nums == null ? false : nums[key] != null;\n" " } else\n" " return this._containsKey\$1(key);\n" @@ -13804,16 +13443,16 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " var rest = this._collection\$_rest;\n" " if (rest == null)\n" " return false;\n" -" return this._findBucketIndex\$2(this._getBucket\$2(rest, key), key) >= 0;\n" +" return this._findBucketIndex\$2(this._collection\$_getBucket\$2(rest, key), key) >= 0;\n" " },\n" " \$index(_, key) {\n" " var strings, t1, nums;\n" " if (typeof key == \"string\" && key !== \"__proto__\") {\n" -" strings = this._strings;\n" +" strings = this._collection\$_strings;\n" " t1 = strings == null ? null : A._HashMap__getTableEntry(strings, key);\n" " return t1;\n" " } else if (typeof key == \"number\" && (key & 1073741823) === key) {\n" -" nums = this._nums;\n" +" nums = this._collection\$_nums;\n" " t1 = nums == null ? null : A._HashMap__getTableEntry(nums, key);\n" " return t1;\n" " } else\n" @@ -13824,7 +13463,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " rest = this._collection\$_rest;\n" " if (rest == null)\n" " return null;\n" -" bucket = this._getBucket\$2(rest, key);\n" +" bucket = this._collection\$_getBucket\$2(rest, key);\n" " index = this._findBucketIndex\$2(bucket, key);\n" " return index < 0 ? null : bucket[index + 1];\n" " },\n" @@ -13834,11 +13473,11 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t1._precomputed1._as(key);\n" " t1._rest[1]._as(value);\n" " if (typeof key == \"string\" && key !== \"__proto__\") {\n" -" strings = _this._strings;\n" -" _this._collection\$_addHashTableEntry\$3(strings == null ? _this._strings = A._HashMap__newHashTable() : strings, key, value);\n" +" strings = _this._collection\$_strings;\n" +" _this._collection\$_addHashTableEntry\$3(strings == null ? _this._collection\$_strings = A._HashMap__newHashTable() : strings, key, value);\n" " } else if (typeof key == \"number\" && (key & 1073741823) === key) {\n" -" nums = _this._nums;\n" -" _this._collection\$_addHashTableEntry\$3(nums == null ? _this._nums = A._HashMap__newHashTable() : nums, key, value);\n" +" nums = _this._collection\$_nums;\n" +" _this._collection\$_addHashTableEntry\$3(nums == null ? _this._collection\$_nums = A._HashMap__newHashTable() : nums, key, value);\n" " } else\n" " _this._set\$2(key, value);\n" " },\n" @@ -13855,7 +13494,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " if (bucket == null) {\n" " A._HashMap__setTableEntry(rest, hash, [key, value]);\n" " ++_this._collection\$_length;\n" -" _this._keys = null;\n" +" _this._collection\$_keys = null;\n" " } else {\n" " index = _this._findBucketIndex\$2(bucket, key);\n" " if (index >= 0)\n" @@ -13863,7 +13502,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " else {\n" " bucket.push(key, value);\n" " ++_this._collection\$_length;\n" -" _this._keys = null;\n" +" _this._collection\$_keys = null;\n" " }\n" " }\n" " },\n" @@ -13877,17 +13516,17 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t2._as(key);\n" " t3 = _this.\$index(0, key);\n" " action.call\$2(key, t3 == null ? t1._as(t3) : t3);\n" -" if (keys !== _this._keys)\n" +" if (keys !== _this._collection\$_keys)\n" " throw A.wrapException(A.ConcurrentModificationError\$(_this));\n" " }\n" " },\n" " _computeKeys\$0() {\n" " var strings, index, names, entries, i, nums, rest, bucket, \$length, i0, _this = this,\n" -" result = _this._keys;\n" +" result = _this._collection\$_keys;\n" " if (result != null)\n" " return result;\n" " result = A.List_List\$filled(_this._collection\$_length, null, false, type\$.dynamic);\n" -" strings = _this._strings;\n" +" strings = _this._collection\$_strings;\n" " index = 0;\n" " if (strings != null) {\n" " names = Object.getOwnPropertyNames(strings);\n" @@ -13897,7 +13536,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " ++index;\n" " }\n" " }\n" -" nums = _this._nums;\n" +" nums = _this._collection\$_nums;\n" " if (nums != null) {\n" " names = Object.getOwnPropertyNames(nums);\n" " entries = names.length;\n" @@ -13919,7 +13558,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " }\n" " }\n" " }\n" -" return _this._keys = result;\n" +" return _this._collection\$_keys = result;\n" " },\n" " _collection\$_addHashTableEntry\$3(table, key, value) {\n" " var t1 = A._instanceType(this);\n" @@ -13927,14 +13566,14 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t1._rest[1]._as(value);\n" " if (table[key] == null) {\n" " ++this._collection\$_length;\n" -" this._keys = null;\n" +" this._collection\$_keys = null;\n" " }\n" " A._HashMap__setTableEntry(table, key, value);\n" " },\n" " _computeHashCode\$1(key) {\n" " return J.get\$hashCode\$(key) & 1073741823;\n" " },\n" -" _getBucket\$2(table, key) {\n" +" _collection\$_getBucket\$2(table, key) {\n" " return table[this._computeHashCode\$1(key)];\n" " },\n" " _findBucketIndex\$2(bucket, key) {\n" @@ -13968,20 +13607,20 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " };\n" " A._HashMapKeyIterable.prototype = {\n" " get\$length(_) {\n" -" return this._collection\$_map._collection\$_length;\n" +" return this._map._collection\$_length;\n" " },\n" " get\$isEmpty(_) {\n" -" return this._collection\$_map._collection\$_length === 0;\n" +" return this._map._collection\$_length === 0;\n" " },\n" " get\$isNotEmpty(_) {\n" -" return this._collection\$_map._collection\$_length !== 0;\n" +" return this._map._collection\$_length !== 0;\n" " },\n" " get\$iterator(_) {\n" -" var t1 = this._collection\$_map;\n" +" var t1 = this._map;\n" " return new A._HashMapKeyIterator(t1, t1._computeKeys\$0(), this.\$ti._eval\$1(\"_HashMapKeyIterator<1>\"));\n" " },\n" " contains\$1(_, element) {\n" -" return this._collection\$_map.containsKey\$1(element);\n" +" return this._map.containsKey\$1(element);\n" " }\n" " };\n" " A._HashMapKeyIterator.prototype = {\n" @@ -13991,10 +13630,10 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " },\n" " moveNext\$0() {\n" " var _this = this,\n" -" keys = _this._keys,\n" +" keys = _this._collection\$_keys,\n" " offset = _this._offset,\n" -" t1 = _this._collection\$_map;\n" -" if (keys !== t1._keys)\n" +" t1 = _this._map;\n" +" if (keys !== t1._collection\$_keys)\n" " throw A.wrapException(A.ConcurrentModificationError\$(t1));\n" " else if (offset >= keys.length) {\n" " _this._collection\$_current = null;\n" @@ -14040,7 +13679,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$1(v) {\n" " return this.K._is(v);\n" " },\n" -" \$signature: 32\n" +" \$signature: 41\n" " };\n" " A._HashSet.prototype = {\n" " get\$iterator(_) {\n" @@ -14058,10 +13697,10 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " contains\$1(_, object) {\n" " var strings, nums;\n" " if (typeof object == \"string\" && object !== \"__proto__\") {\n" -" strings = this._strings;\n" +" strings = this._collection\$_strings;\n" " return strings == null ? false : strings[object] != null;\n" " } else if (typeof object == \"number\" && (object & 1073741823) === object) {\n" -" nums = this._nums;\n" +" nums = this._collection\$_nums;\n" " return nums == null ? false : nums[object] != null;\n" " } else\n" " return this._contains\$1(object);\n" @@ -14076,11 +13715,11 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " var strings, nums, _this = this;\n" " A._instanceType(_this)._precomputed1._as(element);\n" " if (typeof element == \"string\" && element !== \"__proto__\") {\n" -" strings = _this._strings;\n" -" return _this._collection\$_addHashTableEntry\$2(strings == null ? _this._strings = A._HashSet__newHashTable() : strings, element);\n" +" strings = _this._collection\$_strings;\n" +" return _this._collection\$_addHashTableEntry\$2(strings == null ? _this._collection\$_strings = A._HashSet__newHashTable() : strings, element);\n" " } else if (typeof element == \"number\" && (element & 1073741823) === element) {\n" -" nums = _this._nums;\n" -" return _this._collection\$_addHashTableEntry\$2(nums == null ? _this._nums = A._HashSet__newHashTable() : nums, element);\n" +" nums = _this._collection\$_nums;\n" +" return _this._collection\$_addHashTableEntry\$2(nums == null ? _this._collection\$_nums = A._HashSet__newHashTable() : nums, element);\n" " } else\n" " return _this._collection\$_add\$1(element);\n" " },\n" @@ -14106,9 +13745,9 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " remove\$1(_, object) {\n" " var _this = this;\n" " if (typeof object == \"string\" && object !== \"__proto__\")\n" -" return _this._removeHashTableEntry\$2(_this._strings, object);\n" +" return _this._removeHashTableEntry\$2(_this._collection\$_strings, object);\n" " else if (typeof object == \"number\" && (object & 1073741823) === object)\n" -" return _this._removeHashTableEntry\$2(_this._nums, object);\n" +" return _this._removeHashTableEntry\$2(_this._collection\$_nums, object);\n" " else\n" " return _this._remove\$1(object);\n" " },\n" @@ -14135,7 +13774,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " if (result != null)\n" " return result;\n" " result = A.List_List\$filled(_this._collection\$_length, null, false, type\$.dynamic);\n" -" strings = _this._strings;\n" +" strings = _this._collection\$_strings;\n" " index = 0;\n" " if (strings != null) {\n" " names = Object.getOwnPropertyNames(strings);\n" @@ -14145,7 +13784,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " ++index;\n" " }\n" " }\n" -" nums = _this._nums;\n" +" nums = _this._collection\$_nums;\n" " if (nums != null) {\n" " names = Object.getOwnPropertyNames(nums);\n" " entries = names.length;\n" @@ -14369,7 +14008,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t2 = A.S(v);\n" " t1._contents += t2;\n" " },\n" -" \$signature: 18\n" +" \$signature: 17\n" " };\n" " A._UnmodifiableMapMixin.prototype = {\n" " \$indexSet(_, key, value) {\n" @@ -14381,44 +14020,44 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " };\n" " A.MapView.prototype = {\n" " cast\$2\$0(_, \$RK, \$RV) {\n" -" return this._collection\$_map.cast\$2\$0(0, \$RK, \$RV);\n" +" return this._map.cast\$2\$0(0, \$RK, \$RV);\n" " },\n" " \$index(_, key) {\n" -" return this._collection\$_map.\$index(0, key);\n" +" return this._map.\$index(0, key);\n" " },\n" " \$indexSet(_, key, value) {\n" " var t1 = A._instanceType(this);\n" -" this._collection\$_map.\$indexSet(0, t1._precomputed1._as(key), t1._rest[1]._as(value));\n" +" this._map.\$indexSet(0, t1._precomputed1._as(key), t1._rest[1]._as(value));\n" " },\n" " containsKey\$1(key) {\n" -" return this._collection\$_map.containsKey\$1(key);\n" +" return this._map.containsKey\$1(key);\n" " },\n" " forEach\$1(_, action) {\n" -" this._collection\$_map.forEach\$1(0, A._instanceType(this)._eval\$1(\"~(1,2)\")._as(action));\n" +" this._map.forEach\$1(0, A._instanceType(this)._eval\$1(\"~(1,2)\")._as(action));\n" " },\n" " get\$isEmpty(_) {\n" -" var t1 = this._collection\$_map;\n" +" var t1 = this._map;\n" " return t1.get\$isEmpty(t1);\n" " },\n" " get\$isNotEmpty(_) {\n" -" var t1 = this._collection\$_map;\n" +" var t1 = this._map;\n" " return t1.get\$isNotEmpty(t1);\n" " },\n" " get\$length(_) {\n" -" var t1 = this._collection\$_map;\n" +" var t1 = this._map;\n" " return t1.get\$length(t1);\n" " },\n" " get\$keys() {\n" -" return this._collection\$_map.get\$keys();\n" +" return this._map.get\$keys();\n" " },\n" " toString\$0(_) {\n" -" return this._collection\$_map.toString\$0(0);\n" +" return this._map.toString\$0(0);\n" " },\n" " \$isMap: 1\n" " };\n" " A.UnmodifiableMapView.prototype = {\n" " cast\$2\$0(_, \$RK, \$RV) {\n" -" return new A.UnmodifiableMapView(this._collection\$_map.cast\$2\$0(0, \$RK, \$RV), \$RK._eval\$1(\"@<0>\")._bind\$1(\$RV)._eval\$1(\"UnmodifiableMapView<1,2>\"));\n" +" return new A.UnmodifiableMapView(this._map.cast\$2\$0(0, \$RK, \$RV), \$RK._eval\$1(\"@<0>\")._bind\$1(\$RV)._eval\$1(\"UnmodifiableMapView<1,2>\"));\n" " }\n" " };\n" " A.ListQueue.prototype = {\n" @@ -14938,10 +14577,10 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " };\n" " A._JsonMapKeyIterable.prototype = {\n" " get\$length(_) {\n" -" return this._parent.get\$length(0);\n" +" return this._convert\$_parent.get\$length(0);\n" " },\n" " elementAt\$1(_, index) {\n" -" var t1 = this._parent;\n" +" var t1 = this._convert\$_parent;\n" " if (t1._processed == null)\n" " t1 = t1.get\$keys().elementAt\$1(0, index);\n" " else {\n" @@ -14953,7 +14592,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " return t1;\n" " },\n" " get\$iterator(_) {\n" -" var t1 = this._parent;\n" +" var t1 = this._convert\$_parent;\n" " if (t1._processed == null) {\n" " t1 = t1.get\$keys();\n" " t1 = t1.get\$iterator(t1);\n" @@ -14964,7 +14603,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " return t1;\n" " },\n" " contains\$1(_, key) {\n" -" return this._parent.containsKey\$1(key);\n" +" return this._convert\$_parent.containsKey\$1(key);\n" " }\n" " };\n" " A._Utf8Decoder__decoder_closure.prototype = {\n" @@ -14977,7 +14616,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " }\n" " return null;\n" " },\n" -" \$signature: 19\n" +" \$signature: 18\n" " };\n" " A._Utf8Decoder__decoderNonfatal_closure.prototype = {\n" " call\$0() {\n" @@ -14989,7 +14628,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " }\n" " return null;\n" " },\n" -" \$signature: 19\n" +" \$signature: 18\n" " };\n" " A.AsciiCodec.prototype = {\n" " encode\$1(source) {\n" @@ -15422,7 +15061,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " B.JSArray_methods.\$indexSet(t1, t2.i++, key);\n" " B.JSArray_methods.\$indexSet(t1, t2.i++, value);\n" " },\n" -" \$signature: 18\n" +" \$signature: 17\n" " };\n" " A._JsonStringStringifier.prototype = {\n" " get\$_partialResult() {\n" @@ -15813,17 +15452,17 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " \$eq(_, other) {\n" " if (other == null)\n" " return false;\n" -" return other instanceof A.Duration && this._duration === other._duration;\n" +" return other instanceof A.Duration && this.inMicroseconds === other.inMicroseconds;\n" " },\n" " get\$hashCode(_) {\n" -" return B.JSInt_methods.get\$hashCode(this._duration);\n" +" return B.JSInt_methods.get\$hashCode(this.inMicroseconds);\n" " },\n" " compareTo\$1(_, other) {\n" -" return B.JSInt_methods.compareTo\$1(this._duration, type\$.Duration._as(other)._duration);\n" +" return B.JSInt_methods.compareTo\$1(this.inMicroseconds, type\$.Duration._as(other).inMicroseconds);\n" " },\n" " toString\$0(_) {\n" " var sign, minutes, minutesPadding, seconds, secondsPadding,\n" -" microseconds = this._duration,\n" +" microseconds = this.inMicroseconds,\n" " hours = B.JSInt_methods._tdivFast\$1(microseconds, 3600000000),\n" " microseconds0 = microseconds % 3600000000;\n" " if (microseconds < 0) {\n" @@ -16172,7 +15811,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$2(msg, position) {\n" " throw A.wrapException(A.FormatException\$(\"Illegal IPv6 address, \" + msg, this.host, position));\n" " },\n" -" \$signature: 48\n" +" \$signature: 53\n" " };\n" " A._Uri.prototype = {\n" " get\$_text() {\n" @@ -16804,7 +16443,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " var t1 = type\$.JavaScriptFunction;\n" " this._this.then\$1\$2\$onError(new A.FutureOfJSAnyToJSPromise_get_toJS__closure(t1._as(resolve)), new A.FutureOfJSAnyToJSPromise_get_toJS__closure0(t1._as(reject)), type\$.nullable_Object);\n" " },\n" -" \$signature: 20\n" +" \$signature: 19\n" " };\n" " A.FutureOfJSAnyToJSPromise_get_toJS__closure.prototype = {\n" " call\$1(value) {\n" @@ -16830,14 +16469,14 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t1.call(t1, wrapper);\n" " return wrapper;\n" " },\n" -" \$signature: 59\n" +" \$signature: 61\n" " };\n" " A.FutureOfVoidToJSPromise_get_toJS_closure.prototype = {\n" " call\$2(resolve, reject) {\n" " var t1 = type\$.JavaScriptFunction;\n" " this._this.then\$1\$2\$onError(new A.FutureOfVoidToJSPromise_get_toJS__closure(t1._as(resolve)), new A.FutureOfVoidToJSPromise_get_toJS__closure0(t1._as(reject)), type\$.nullable_Object);\n" " },\n" -" \$signature: 20\n" +" \$signature: 19\n" " };\n" " A.FutureOfVoidToJSPromise_get_toJS__closure.prototype = {\n" " call\$1(__wc0_formal) {\n" @@ -17369,7 +17008,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$1(e) {\n" " return type\$.BuildStatus._as(e)._name === this.json;\n" " },\n" -" \$signature: 73\n" +" \$signature: 29\n" " };\n" " A.BuildStatus_BuildStatus\$fromJson_closure0.prototype = {\n" " call\$0() {\n" @@ -17451,7 +17090,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$1(e) {\n" " return type\$.DebugEvent._as(e).toJson\$0();\n" " },\n" -" \$signature: 89\n" +" \$signature: 75\n" " };\n" " A.DebugInfo.prototype = {\n" " toJson\$0() {\n" @@ -17829,13 +17468,13 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$0() {\n" " return true;\n" " },\n" -" \$signature: 21\n" +" \$signature: 20\n" " };\n" " A.BatchedStreamController__hasEventDuring_closure.prototype = {\n" " call\$0() {\n" " return false;\n" " },\n" -" \$signature: 21\n" +" \$signature: 20\n" " };\n" " A.SocketClient.prototype = {};\n" " A.SseSocketClient.prototype = {\n" @@ -18043,7 +17682,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " type\$.WebSocket._as(socket);\n" " return new A.PersistentWebSocket(_this.logger, _this.debugName, _this.maxRetryAttempts, new A._AsyncCompleter(new A._Future(\$.Zone__current, type\$._Future_void), type\$._AsyncCompleter_void), _this.uri, _this.onReconnect, socket, A.StreamController_StreamController(type\$.dynamic));\n" " },\n" -" \$signature: 29\n" +" \$signature: 31\n" " };\n" " A.PersistentWebSocket__listenWithRetry_attemptRetry.prototype = {\n" " call\$1(message) {\n" @@ -18070,7 +17709,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " });\n" " return A._asyncStartSync(\$async\$call\$1, \$async\$completer);\n" " },\n" -" \$signature: 22\n" +" \$signature: 21\n" " };\n" " A.PersistentWebSocket__listenWithRetry_closure.prototype = {\n" " call\$1(e) {\n" @@ -18483,7 +18122,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " buffer._contents = t1;\n" " buffer._contents = t1 + this.subtype;\n" " t1 = this.parameters;\n" -" t1._collection\$_map.forEach\$1(0, t1.\$ti._eval\$1(\"~(1,2)\")._as(new A.MediaType_toString_closure(buffer)));\n" +" t1._map.forEach\$1(0, t1.\$ti._eval\$1(\"~(1,2)\")._as(new A.MediaType_toString_closure(buffer)));\n" " t1 = buffer._contents;\n" " return t1.charCodeAt(0) == 0 ? t1 : t1;\n" " }\n" @@ -18573,7 +18212,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$1(match) {\n" " return \"\\\\\" + A.S(match.\$index(0, 0));\n" " },\n" -" \$signature: 23\n" +" \$signature: 22\n" " };\n" " A.expectQuotedString_closure.prototype = {\n" " call\$1(match) {\n" @@ -18581,7 +18220,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t1.toString;\n" " return t1;\n" " },\n" -" \$signature: 23\n" +" \$signature: 22\n" " };\n" " A.Level.prototype = {\n" " \$eq(_, other) {\n" @@ -18904,13 +18543,13 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " call\$1(part) {\n" " return A._asString(part) !== \"\";\n" " },\n" -" \$signature: 24\n" +" \$signature: 23\n" " };\n" " A.Context_split_closure.prototype = {\n" " call\$1(part) {\n" " return A._asString(part).length !== 0;\n" " },\n" -" \$signature: 24\n" +" \$signature: 23\n" " };\n" " A._validateArgList_closure.prototype = {\n" " call\$1(arg) {\n" @@ -19362,7 +19001,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t1._restartable_timer\$_timer.cancel\$0();\n" " else {\n" " t1._restartable_timer\$_timer.cancel\$0();\n" -" t1._restartable_timer\$_timer = A.Timer_Timer(t1._restartable_timer\$_duration, t1._restartable_timer\$_callback);\n" +" t1._restartable_timer\$_timer = A.Timer_Timer(t1._duration, t1._restartable_timer\$_callback);\n" " }\n" " }\n" " };\n" @@ -19893,7 +19532,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " }\n" " return lines;\n" " },\n" -" \$signature: 52\n" +" \$signature: 78\n" " };\n" " A.Highlighter__collateLines__closure.prototype = {\n" " call\$1(highlight) {\n" @@ -20004,7 +19643,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t2._contents = t4;\n" " return t4.length - t3.length;\n" " },\n" -" \$signature: 25\n" +" \$signature: 24\n" " };\n" " A.Highlighter__writeIndicator_closure0.prototype = {\n" " call\$0() {\n" @@ -20024,7 +19663,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t1._writeArrow\$3\$beginning(_this.line, Math.max(_this.highlight.span.get\$end().get\$column() - 1, 0), false);\n" " return t2._contents.length - t3.length;\n" " },\n" -" \$signature: 25\n" +" \$signature: 24\n" " };\n" " A.Highlighter__writeSidebar_closure.prototype = {\n" " call\$0() {\n" @@ -20884,7 +20523,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t1 = type\$.dynamic;\n" " A._trySendEvent(this.client.get\$sink(), B.C_JsonCodec.encode\$2\$toEncodable(A._setArrayType([\"HotRestartRequest\", A.LinkedHashMap_LinkedHashMap\$_literal([\"id\", runId], type\$.String, t1)], type\$.JSArray_Object), null), t1);\n" " },\n" -" \$signature: 17\n" +" \$signature: 25\n" " };\n" " A.main__closure4.prototype = {\n" " call\$0() {\n" @@ -20924,7 +20563,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " A._asString(eventData);\n" " A._trySendEvent(this.client.get\$sink(), B.C_JsonCodec.encode\$2\$toEncodable(A._setArrayType([\"RegisterEvent\", new A.RegisterEvent(eventData, Date.now()).toJson\$0()], type\$.JSArray_Object), null), type\$.dynamic);\n" " },\n" -" \$signature: 17\n" +" \$signature: 25\n" " };\n" " A.main__closure8.prototype = {\n" " call\$0() {\n" @@ -21128,7 +20767,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " });\n" " return A._asyncStartSync(\$async\$call\$1, \$async\$completer);\n" " },\n" -" \$signature: 22\n" +" \$signature: 21\n" " };\n" " A.main__closure10.prototype = {\n" " call\$1(error) {\n" @@ -21890,7 +21529,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _reload\$body\$RequireRestarter(modules) {\n" " var \$async\$goto = 0,\n" " \$async\$completer = A._makeAsyncAwaitCompleter(type\$.bool),\n" -" \$async\$returnValue, \$async\$handler = 2, \$async\$errorStack = [], \$async\$self = this, reloadedModules, moduleId, parentIds, e, _box_0, t4, t5, t6, t7, t8, t9, t10, _this, parentIds0, result, exception, t1, t2, dart, t3, \$async\$exception;\n" +" \$async\$returnValue, \$async\$handler = 2, \$async\$errorStack = [], \$async\$self = this, reloadedModules, moduleId, parentIds, e, _box_0, t4, t5, t6, t7, t8, t9, _this, parentIds0, exception, t1, t2, dart, t3, \$async\$exception;\n" " var \$async\$_reload\$1 = A._wrapJsFunctionForAsync(function(\$async\$errorCode, \$async\$result) {\n" " if (\$async\$errorCode === 1) {\n" " \$async\$errorStack.push(\$async\$result);\n" @@ -21926,57 +21565,48 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " t3 === \$ && A.throwLateFieldNI(\"_dirtyModules\");\n" " t3.addAll\$1(0, modules);\n" " _box_0.previousModuleId = null;\n" -" t3 = \$async\$self.get\$_moduleTopologicalCompare(), t4 = type\$.String, t5 = type\$.nullable_JSArray_nullable_Object, t6 = type\$.JSArray_String, t7 = A._callDartFunctionFast0;\n" +" t3 = \$async\$self.get\$_moduleTopologicalCompare(), t4 = type\$.String, t5 = type\$.nullable_JSArray_nullable_Object, t6 = type\$.JSArray_String;\n" " case 10:\n" " // for condition\n" -" if (!(t8 = \$async\$self.__RequireRestarter__dirtyModules_A, t9 = t8._root, t10 = t9 == null, !t10)) {\n" +" if (!(t7 = \$async\$self.__RequireRestarter__dirtyModules_A, t8 = t7._root, t9 = t8 == null, !t9)) {\n" " // goto after for\n" " \$async\$goto = 11;\n" " break;\n" " }\n" -" if (t10)\n" +" if (t9)\n" " A.throwExpression(A.IterableElementError_noElement());\n" -" t9 = t8._splayMin\$1(t9);\n" -" t8._root = t9;\n" -" moduleId = t9.key;\n" +" t8 = t7._splayMin\$1(t8);\n" +" t7._root = t8;\n" +" moduleId = t8.key;\n" " \$async\$self.__RequireRestarter__dirtyModules_A.remove\$1(0, moduleId);\n" " _this = A._asString(moduleId);\n" -" t9 = t5._as(t2._as(t2._as(t1.\$requireLoader).moduleParentsGraph).get(_this));\n" -" if (t9 == null)\n" +" t8 = t5._as(t2._as(t2._as(t1.\$requireLoader).moduleParentsGraph).get(_this));\n" +" if (t8 == null)\n" " parentIds0 = null;\n" " else {\n" -" t8 = A.JSArrayExtension_toDartIterable(t9, t4);\n" -" t8 = A.List_List\$_of(t8, t8.\$ti._eval\$1(\"ListIterable.E\"));\n" -" parentIds0 = t8;\n" +" t7 = A.JSArrayExtension_toDartIterable(t8, t4);\n" +" t7 = A.List_List\$_of(t7, t7.\$ti._eval\$1(\"ListIterable.E\"));\n" +" parentIds0 = t7;\n" " }\n" " parentIds = parentIds0 == null ? A._setArrayType([], t6) : parentIds0;\n" " \$async\$goto = J.get\$length\$asx(parentIds) === 0 ? 12 : 14;\n" " break;\n" " case 12:\n" " // then\n" -" t8 = new A.RequireRestarter__reload_closure(_box_0, dart);\n" -" if (typeof t8 == \"function\")\n" -" A.throwExpression(A.ArgumentError\$(\"Attempting to rewrap a JS function.\", null));\n" -" result = function(_call, f) {\n" -" return function() {\n" -" return _call(f);\n" -" };\n" -" }(t7, t8);\n" -" result[\$.\$get\$DART_CLOSURE_DART_JSINTEROP_PROPERTY_NAME()] = t8;\n" -" t1.\$dartRunMain = result;\n" +" t1.\$dartRunMain = A._functionToJS0(new A.RequireRestarter__reload_closure(_box_0, dart));\n" " // goto join\n" " \$async\$goto = 13;\n" " break;\n" " case 14:\n" " // else\n" -" t8 = reloadedModules;\n" -" if (typeof t8 !== \"number\") {\n" -" \$async\$returnValue = t8.\$add();\n" +" t7 = reloadedModules;\n" +" if (typeof t7 !== \"number\") {\n" +" \$async\$returnValue = t7.\$add();\n" " // goto return\n" " \$async\$goto = 1;\n" " break;\n" " }\n" -" reloadedModules = t8 + 1;\n" +" reloadedModules = t7 + 1;\n" " \$async\$goto = 15;\n" " return A._asyncAwait(\$async\$self._reloadModule\$1(moduleId), \$async\$_reload\$1);\n" " case 15:\n" @@ -22049,7 +21679,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " stronglyConnectedComponents = A.stronglyConnectedComponents(A.JSArrayExtension_toDartIterable(type\$.JSArray_nullable_Object._as(t1.Array.from(A._asJSObject(t2.keys()))), t3), this.get\$_moduleParents(), t3);\n" " t3 = this._moduleOrdering;\n" " if (t3._collection\$_length > 0) {\n" -" t3._strings = t3._nums = t3._collection\$_rest = t3._keys = null;\n" +" t3._collection\$_strings = t3._collection\$_nums = t3._collection\$_rest = t3._collection\$_keys = null;\n" " t3._collection\$_length = 0;\n" " }\n" " for (i = 0; i < stronglyConnectedComponents.length; ++i)\n" @@ -22139,11 +21769,11 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _instance_1_u = hunkHelpers._instance_1u,\n" " _static_1 = hunkHelpers._static_1,\n" " _static_0 = hunkHelpers._static_0,\n" -" _static = hunkHelpers.installStaticTearOff,\n" " _instance = hunkHelpers.installInstanceTearOff,\n" " _instance_2_u = hunkHelpers._instance_2u,\n" " _instance_0_u = hunkHelpers._instance_0u,\n" -" _instance_1_i = hunkHelpers._instance_1i;\n" +" _instance_1_i = hunkHelpers._instance_1i,\n" +" _static = hunkHelpers.installStaticTearOff;\n" " _static_2(J, \"_interceptors_JSArray__compareAny\$closure\", \"JSArray__compareAny\", 27);\n" " _instance_1_u(A.CastStreamSubscription.prototype, \"get\$__internal\$_onData\", \"__internal\$_onData\$1\", 11);\n" " _static_1(A, \"async__AsyncRun__scheduleImmediateJsOverride\$closure\", \"_AsyncRun__scheduleImmediateJsOverride\", 14);\n" @@ -22153,34 +21783,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _static_1(A, \"async___nullDataHandler\$closure\", \"_nullDataHandler\", 4);\n" " _static_2(A, \"async___nullErrorHandler\$closure\", \"_nullErrorHandler\", 7);\n" " _static_0(A, \"async___nullDoneHandler\$closure\", \"_nullDoneHandler\", 0);\n" -" _static(A, \"async___rootHandleUncaughtError\$closure\", 5, null, [\"call\$5\"], [\"_rootHandleUncaughtError\"], 75, 0);\n" -" _static(A, \"async___rootRun\$closure\", 4, null, [\"call\$1\$4\", \"call\$4\"], [\"_rootRun\", function(\$self, \$parent, zone, f) {\n" -" return A._rootRun(\$self, \$parent, zone, f, type\$.dynamic);\n" -" }], 76, 0);\n" -" _static(A, \"async___rootRunUnary\$closure\", 5, null, [\"call\$2\$5\", \"call\$5\"], [\"_rootRunUnary\", function(\$self, \$parent, zone, f, arg) {\n" -" var t1 = type\$.dynamic;\n" -" return A._rootRunUnary(\$self, \$parent, zone, f, arg, t1, t1);\n" -" }], 77, 0);\n" -" _static(A, \"async___rootRunBinary\$closure\", 6, null, [\"call\$3\$6\"], [\"_rootRunBinary\"], 78, 0);\n" -" _static(A, \"async___rootRegisterCallback\$closure\", 4, null, [\"call\$1\$4\", \"call\$4\"], [\"_rootRegisterCallback\", function(\$self, \$parent, zone, f) {\n" -" return A._rootRegisterCallback(\$self, \$parent, zone, f, type\$.dynamic);\n" -" }], 79, 0);\n" -" _static(A, \"async___rootRegisterUnaryCallback\$closure\", 4, null, [\"call\$2\$4\", \"call\$4\"], [\"_rootRegisterUnaryCallback\", function(\$self, \$parent, zone, f) {\n" -" var t1 = type\$.dynamic;\n" -" return A._rootRegisterUnaryCallback(\$self, \$parent, zone, f, t1, t1);\n" -" }], 80, 0);\n" -" _static(A, \"async___rootRegisterBinaryCallback\$closure\", 4, null, [\"call\$3\$4\", \"call\$4\"], [\"_rootRegisterBinaryCallback\", function(\$self, \$parent, zone, f) {\n" -" var t1 = type\$.dynamic;\n" -" return A._rootRegisterBinaryCallback(\$self, \$parent, zone, f, t1, t1, t1);\n" -" }], 81, 0);\n" -" _static(A, \"async___rootErrorCallback\$closure\", 5, null, [\"call\$5\"], [\"_rootErrorCallback\"], 82, 0);\n" -" _static(A, \"async___rootScheduleMicrotask\$closure\", 4, null, [\"call\$4\"], [\"_rootScheduleMicrotask\"], 83, 0);\n" -" _static(A, \"async___rootCreateTimer\$closure\", 5, null, [\"call\$5\"], [\"_rootCreateTimer\"], 84, 0);\n" -" _static(A, \"async___rootCreatePeriodicTimer\$closure\", 5, null, [\"call\$5\"], [\"_rootCreatePeriodicTimer\"], 85, 0);\n" -" _static(A, \"async___rootPrint\$closure\", 4, null, [\"call\$4\"], [\"_rootPrint\"], 86, 0);\n" -" _static_1(A, \"async___printToZone\$closure\", \"_printToZone0\", 87);\n" -" _static(A, \"async___rootFork\$closure\", 5, null, [\"call\$5\"], [\"_rootFork\"], 88, 0);\n" -" _instance(A._Completer.prototype, \"get\$completeError\", 0, 1, null, [\"call\$2\", \"call\$1\"], [\"completeError\$2\", \"completeError\$1\"], 53, 0, 0);\n" +" _instance(A._Completer.prototype, \"get\$completeError\", 0, 1, null, [\"call\$2\", \"call\$1\"], [\"completeError\$2\", \"completeError\$1\"], 58, 0, 0);\n" " _instance_2_u(A._Future.prototype, \"get\$_completeError\", \"_completeError\$2\", 7);\n" " var _;\n" " _instance_0_u(_ = A._ControllerSubscription.prototype, \"get\$_onPause\", \"_onPause\$0\", 0);\n" @@ -22191,7 +21794,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _instance_0_u(_ = A._ForwardingStreamSubscription.prototype, \"get\$_onPause\", \"_onPause\$0\", 0);\n" " _instance_0_u(_, \"get\$_onResume\", \"_onResume\$0\", 0);\n" " _instance_1_u(_, \"get\$_handleData\", \"_handleData\$1\", 11);\n" -" _instance_2_u(_, \"get\$_handleError\", \"_handleError\$2\", 92);\n" +" _instance_2_u(_, \"get\$_handleError\", \"_handleError\$2\", 76);\n" " _instance_0_u(_, \"get\$_handleDone\", \"_handleDone\$0\", 0);\n" " _static_2(A, \"collection___defaultEquals\$closure\", \"_defaultEquals0\", 28);\n" " _static_1(A, \"collection___defaultHashCode\$closure\", \"_defaultHashCode\", 15);\n" @@ -22204,7 +21807,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _static_1(A, \"core_Uri_decodeComponent\$closure\", \"Uri_decodeComponent\", 9);\n" " _static(A, \"math__max\$closure\", 2, null, [\"call\$1\$2\", \"call\$2\"], [\"max\", function(a, b) {\n" " return A.max(a, b, type\$.num);\n" -" }], 91, 0);\n" +" }], 77, 0);\n" " _instance_1_u(_ = A.PersistentWebSocket.prototype, \"get\$_writeToWebSocket\", \"_writeToWebSocket\$1\", 4);\n" " _instance_0_u(_, \"get\$_listenWithRetry\", \"_listenWithRetry\$0\", 6);\n" " _static_1(A, \"case_insensitive_map_CaseInsensitiveMap__canonicalizer\$closure\", \"CaseInsensitiveMap__canonicalizer\", 9);\n" @@ -22212,7 +21815,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _instance_1_u(_, \"get\$_onIncomingMessage\", \"_onIncomingMessage\$1\", 2);\n" " _instance_0_u(_, \"get\$_onOutgoingDone\", \"_onOutgoingDone\$0\", 0);\n" " _instance_1_u(_, \"get\$_onOutgoingMessage\", \"_onOutgoingMessage\$1\", 56);\n" -" _static_1(A, \"client__initializeConnection\$closure\", \"initializeConnection\", 61);\n" +" _static_1(A, \"client__initializeConnection\$closure\", \"initializeConnection\", 52);\n" " _static_1(A, \"client___handleAuthRequest\$closure\", \"_handleAuthRequest\", 2);\n" " _instance_0_u(A.ReloadingManager.prototype, \"get\$hotRestartEnd\", \"hotRestartEnd\$0\", 0);\n" " _instance_1_u(_ = A.RequireRestarter.prototype, \"get\$_moduleParents\", \"_moduleParents\$1\", 69);\n" @@ -22223,7 +21826,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _inherit = hunkHelpers.inherit,\n" " _inheritMany = hunkHelpers.inheritMany;\n" " _inherit(A.Object, null);\n" -" _inheritMany(A.Object, [A.JS_CONST, J.Interceptor, A.SafeToStringHook, J.ArrayIterator, A.Stream, A.CastStreamSubscription, A.Iterable, A.CastIterator, A.Closure, A.MapBase, A.Error, A.ListBase, A.SentinelValue, A.ListIterator, A.MappedIterator, A.WhereIterator, A.ExpandIterator, A.TakeIterator, A.SkipIterator, A.EmptyIterator, A.WhereTypeIterator, A.FixedLengthListMixin, A.UnmodifiableListMixin, A._Record, A.ConstantMap, A._KeysOrValuesOrElementsIterator, A.TypeErrorDecoder, A.NullThrownFromJavaScriptException, A.ExceptionAndStackTrace, A._StackTrace, A.LinkedHashMapCell, A.LinkedHashMapKeyIterator, A.LinkedHashMapValueIterator, A.LinkedHashMapEntryIterator, A.JSSyntaxRegExp, A._MatchImplementation, A._AllMatchesIterator, A.StringMatch, A._StringAllMatchesIterator, A._Cell, A._UnmodifiableNativeByteBufferView, A.Rti, A._FunctionParameters, A._Type, A._TimerImpl, A._AsyncAwaitCompleter, A.AsyncError, A._Completer, A._FutureListener, A._Future, A._AsyncCallbackEntry, A._StreamController, A._AsyncStreamControllerDispatch, A._BufferingStreamSubscription, A._StreamSinkWrapper, A._DelayedEvent, A._DelayedDone, A._PendingEvents, A._DoneStreamSubscription, A._StreamIterator, A._ZoneFunction, A._Zone, A._ZoneDelegate, A._ZoneSpecification, A._HashMapKeyIterator, A.SetBase, A._HashSetIterator, A._UnmodifiableMapMixin, A.MapView, A._ListQueueIterator, A._SplayTreeNode, A._SplayTree, A._SplayTreeIterator, A.Codec, A.Converter, A.ByteConversionSink, A._JsonStringifier, A._Utf8Encoder, A._Utf8Decoder, A.DateTime, A.Duration, A._Enum, A.OutOfMemoryError, A.StackOverflowError, A._Exception, A.FormatException, A.MapEntry, A.Null, A._StringStackTrace, A.StringBuffer, A._Uri, A.UriData, A._SimpleUri, A.NullRejectionException, A._JSRandom, A._JSSecureRandom, A.AsyncMemoizer, A.ErrorResult, A.ValueResult, A.StreamQueue, A._NextRequest, A._HasNextRequest, A.CanonicalizedMap, A._QueueList_Object_ListMixin, A.BuildResult, A.ConnectRequest, A.DebugEvent, A.BatchedDebugEvents, A.DebugInfo, A.DevToolsRequest, A.DevToolsResponse, A.ErrorResponse, A.HotReloadRequest, A.HotReloadResponse, A.HotRestartRequest, A.HotRestartResponse, A.PingRequest, A.RegisterEvent, A.RunRequest, A.ServiceExtensionRequest, A.ServiceExtensionResponse, A.BatchedStreamController, A.SocketClient, A._PersistentWebSocket_Object_StreamChannelMixin, A.Uuid, A._StackState, A.ClientException, A.BaseClient, A.BaseRequest, A.BaseResponse, A.MediaType, A.Level, A.LogRecord, A.Logger, A.Context, A.Style, A.ParsedPath, A.PathException, A.Pool, A.PoolResource, A.SourceFile, A.SourceLocationMixin, A.SourceSpanMixin, A.Highlighter, A._Highlight, A._Line, A.SourceLocation, A.SourceSpanException, A.StreamChannelMixin, A.StringScanner, A.EventStreamProvider, A._EventStreamSubscription, A.BrowserWebSocket, A.WebSocketEvent, A.WebSocketException, A.DdcLibraryBundleRestarter, A.DdcRestarter, A.ReloadingManager, A.HotReloadFailedException, A.RequireRestarter]);\n" +" _inheritMany(A.Object, [A.JS_CONST, J.Interceptor, A.SafeToStringHook, J.ArrayIterator, A.Stream, A.CastStreamSubscription, A.Iterable, A.CastIterator, A.Closure, A.MapBase, A.Error, A.ListBase, A.SentinelValue, A.ListIterator, A.MappedIterator, A.WhereIterator, A.ExpandIterator, A.TakeIterator, A.SkipIterator, A.EmptyIterator, A.WhereTypeIterator, A.FixedLengthListMixin, A.UnmodifiableListMixin, A._Record, A.ConstantMap, A._KeysOrValuesOrElementsIterator, A.TypeErrorDecoder, A.NullThrownFromJavaScriptException, A.ExceptionAndStackTrace, A._StackTrace, A.LinkedHashMapCell, A.LinkedHashMapKeyIterator, A.LinkedHashMapValueIterator, A.LinkedHashMapEntryIterator, A.JSSyntaxRegExp, A._MatchImplementation, A._AllMatchesIterator, A.StringMatch, A._StringAllMatchesIterator, A._Cell, A._UnmodifiableNativeByteBufferView, A.Rti, A._FunctionParameters, A._Type, A._TimerImpl, A._AsyncAwaitCompleter, A.AsyncError, A._Completer, A._FutureListener, A._Future, A._AsyncCallbackEntry, A._StreamController, A._AsyncStreamControllerDispatch, A._BufferingStreamSubscription, A._StreamSinkWrapper, A._DelayedEvent, A._DelayedDone, A._PendingEvents, A._DoneStreamSubscription, A._StreamIterator, A._ZoneHandleUncaughtError, A.Zone, A.ZoneDelegate, A.ZoneSpecification, A._HashMapKeyIterator, A.SetBase, A._HashSetIterator, A._UnmodifiableMapMixin, A.MapView, A._ListQueueIterator, A._SplayTreeNode, A._SplayTree, A._SplayTreeIterator, A.Codec, A.Converter, A.ByteConversionSink, A._JsonStringifier, A._Utf8Encoder, A._Utf8Decoder, A.DateTime, A.Duration, A._Enum, A.OutOfMemoryError, A.StackOverflowError, A._Exception, A.FormatException, A.MapEntry, A.Null, A._StringStackTrace, A.StringBuffer, A._Uri, A.UriData, A._SimpleUri, A.NullRejectionException, A._JSRandom, A._JSSecureRandom, A.AsyncMemoizer, A.ErrorResult, A.ValueResult, A.StreamQueue, A._NextRequest, A._HasNextRequest, A.CanonicalizedMap, A._QueueList_Object_ListMixin, A.BuildResult, A.ConnectRequest, A.DebugEvent, A.BatchedDebugEvents, A.DebugInfo, A.DevToolsRequest, A.DevToolsResponse, A.ErrorResponse, A.HotReloadRequest, A.HotReloadResponse, A.HotRestartRequest, A.HotRestartResponse, A.PingRequest, A.RegisterEvent, A.RunRequest, A.ServiceExtensionRequest, A.ServiceExtensionResponse, A.BatchedStreamController, A.SocketClient, A._PersistentWebSocket_Object_StreamChannelMixin, A.Uuid, A._StackState, A.ClientException, A.BaseClient, A.BaseRequest, A.BaseResponse, A.MediaType, A.Level, A.LogRecord, A.Logger, A.Context, A.Style, A.ParsedPath, A.PathException, A.Pool, A.PoolResource, A.SourceFile, A.SourceLocationMixin, A.SourceSpanMixin, A.Highlighter, A._Highlight, A._Line, A.SourceLocation, A.SourceSpanException, A.StreamChannelMixin, A.StringScanner, A.EventStreamProvider, A._EventStreamSubscription, A.BrowserWebSocket, A.WebSocketEvent, A.WebSocketException, A.DdcLibraryBundleRestarter, A.DdcRestarter, A.ReloadingManager, A.HotReloadFailedException, A.RequireRestarter]);\n" " _inheritMany(J.Interceptor, [J.JSBool, J.JSNull, J.JavaScriptObject, J.JavaScriptBigInt, J.JavaScriptSymbol, J.JSNumber, J.JSString]);\n" " _inheritMany(J.JavaScriptObject, [J.LegacyJavaScriptObject, J.JSArray, A.NativeByteBuffer, A.NativeTypedData]);\n" " _inheritMany(J.LegacyJavaScriptObject, [J.PlainJavaScriptObject, J.UnknownJavaScriptObject, J.JavaScriptFunction]);\n" @@ -22235,14 +21838,14 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _inheritMany(A._CastIterableBase, [A.CastIterable, A.__CastListBase__CastIterableBase_ListMixin]);\n" " _inherit(A._EfficientLengthCastIterable, A.CastIterable);\n" " _inherit(A._CastListBase, A.__CastListBase__CastIterableBase_ListMixin);\n" -" _inheritMany(A.Closure, [A.Closure2Args, A.Closure0Args, A.Instantiation, A.TearOffClosure, A.initHooks_closure, A.initHooks_closure1, A._AsyncRun__initializeScheduleImmediate_internalCallback, A._AsyncRun__initializeScheduleImmediate_closure, A._awaitOnObject_closure, A._Future__propagateToListeners_handleWhenCompleteCallback_closure, A._Future_timeout_closure0, A.Stream_length_closure, A.Stream_first_closure0, A._CustomZone_bindUnaryCallback_closure, A._CustomZone_bindUnaryCallbackGuarded_closure, A._RootZone_bindUnaryCallback_closure, A._RootZone_bindUnaryCallbackGuarded_closure, A.runZonedGuarded_closure, A._LinkedCustomHashMap_closure, A._Uri__makePath_closure, A.FutureOfJSAnyToJSPromise_get_toJS__closure, A.FutureOfVoidToJSPromise_get_toJS__closure, A.jsify__convert, A.promiseToFuture_closure, A.promiseToFuture_closure0, A.dartify_convert, A.StreamQueue__ensureListening_closure, A.CanonicalizedMap_keys_closure, A.BuildStatus_BuildStatus\$fromJson_closure, A.BatchedDebugEvents_toJson_closure, A.WebSocketClient_stream_closure, A.PersistentWebSocket_connect_closure, A.PersistentWebSocket__listenWithRetry_attemptRetry, A.PersistentWebSocket__listenWithRetry_closure, A.BaseRequest_closure0, A.BrowserClient_send_closure, A._bodyToStream_closure, A.ByteStream_toBytes_closure, A.MediaType_toString__closure, A.expectQuotedString_closure, A.Context_joinAll_closure, A.Context_split_closure, A._validateArgList_closure, A.Pool__runOnRelease_closure, A.Highlighter\$__closure, A.Highlighter\$___closure, A.Highlighter\$__closure0, A.Highlighter__collateLines_closure, A.Highlighter__collateLines_closure1, A.Highlighter__collateLines__closure, A.Highlighter_highlight_closure, A.SseClient_closure0, A.SseClient_closure1, A._EventStreamSubscription_closure, A._EventStreamSubscription_onData_closure, A.BrowserWebSocket_connect_closure, A.BrowserWebSocket_connect_closure0, A.BrowserWebSocket_connect_closure1, A.BrowserWebSocket_connect_closure2, A.main__closure2, A.main__closure3, A.main__closure5, A.main__closure7, A.main__closure9, A.main__closure10, A.main__closure11, A._handleAuthRequest_closure, A._sendHotReloadResponse_closure, A._sendHotRestartResponse_closure, A.DdcLibraryBundleRestarter_restart_closure, A.DdcLibraryBundleRestarter_hotReloadStart_closure, A.DdcRestarter_restart_closure0, A.DdcRestarter_restart_closure, A.RequireRestarter__reloadModule_closure0, A.JSArrayExtension_toDartIterable_closure]);\n" +" _inheritMany(A.Closure, [A.Closure2Args, A.Closure0Args, A.Instantiation, A.TearOffClosure, A.initHooks_closure, A.initHooks_closure1, A._AsyncRun__initializeScheduleImmediate_internalCallback, A._AsyncRun__initializeScheduleImmediate_closure, A._awaitOnObject_closure, A._Future__propagateToListeners_handleWhenCompleteCallback_closure, A._Future_timeout_closure0, A.Stream_length_closure, A.Stream_first_closure0, A.Zone_bindUnaryCallbackGuarded_closure, A.runZonedGuarded_errorHandler, A._LinkedCustomHashMap_closure, A._Uri__makePath_closure, A.FutureOfJSAnyToJSPromise_get_toJS__closure, A.FutureOfVoidToJSPromise_get_toJS__closure, A.jsify__convert, A.promiseToFuture_closure, A.promiseToFuture_closure0, A.dartify_convert, A.StreamQueue__ensureListening_closure, A.CanonicalizedMap_keys_closure, A.BuildStatus_BuildStatus\$fromJson_closure, A.BatchedDebugEvents_toJson_closure, A.WebSocketClient_stream_closure, A.PersistentWebSocket_connect_closure, A.PersistentWebSocket__listenWithRetry_attemptRetry, A.PersistentWebSocket__listenWithRetry_closure, A.BaseRequest_closure0, A.BrowserClient_send_closure, A._bodyToStream_closure, A.ByteStream_toBytes_closure, A.MediaType_toString__closure, A.expectQuotedString_closure, A.Context_joinAll_closure, A.Context_split_closure, A._validateArgList_closure, A.Pool__runOnRelease_closure, A.Highlighter\$__closure, A.Highlighter\$___closure, A.Highlighter\$__closure0, A.Highlighter__collateLines_closure, A.Highlighter__collateLines_closure1, A.Highlighter__collateLines__closure, A.Highlighter_highlight_closure, A.SseClient_closure0, A.SseClient_closure1, A._EventStreamSubscription_closure, A._EventStreamSubscription_onData_closure, A.BrowserWebSocket_connect_closure, A.BrowserWebSocket_connect_closure0, A.BrowserWebSocket_connect_closure1, A.BrowserWebSocket_connect_closure2, A.main__closure2, A.main__closure3, A.main__closure5, A.main__closure7, A.main__closure9, A.main__closure10, A.main__closure11, A._handleAuthRequest_closure, A._sendHotReloadResponse_closure, A._sendHotRestartResponse_closure, A.DdcLibraryBundleRestarter_restart_closure, A.DdcLibraryBundleRestarter_hotReloadStart_closure, A.DdcRestarter_restart_closure0, A.DdcRestarter_restart_closure, A.RequireRestarter__reloadModule_closure0, A.JSArrayExtension_toDartIterable_closure]);\n" " _inheritMany(A.Closure2Args, [A._CastListBase_sort_closure, A.CastMap_forEach_closure, A.initHooks_closure0, A._awaitOnObject_closure0, A._wrapJsFunctionForAsync_closure, A._Future__propagateToListeners_handleWhenCompleteCallback_closure0, A._Future_timeout_closure1, A._BufferingStreamSubscription_asFuture_closure0, A.MapBase_mapToString_closure, A._JsonStringifier_writeMap_closure, A.Uri_parseIPv6Address_error, A.FutureOfJSAnyToJSPromise_get_toJS_closure, A.FutureOfJSAnyToJSPromise_get_toJS__closure0, A.FutureOfVoidToJSPromise_get_toJS_closure, A.FutureOfVoidToJSPromise_get_toJS__closure0, A.StreamQueue__ensureListening_closure1, A.CanonicalizedMap_addAll_closure, A.CanonicalizedMap_forEach_closure, A.safeUnawaited_closure, A.BaseRequest_closure, A.MediaType_toString_closure, A.Pool__runOnRelease_closure0, A.Highlighter__collateLines_closure0, A.main__closure6, A.main_closure0]);\n" " _inherit(A.CastList, A._CastListBase);\n" " _inheritMany(A.MapBase, [A.CastMap, A.JsLinkedHashMap, A._HashMap, A._JsonMap]);\n" " _inheritMany(A.Error, [A.LateError, A.TypeError, A.JsNoSuchMethodError, A.UnknownJsTypeError, A.RuntimeError, A._Error, A.JsonUnsupportedObjectError, A.AssertionError, A.ArgumentError, A.UnsupportedError, A.UnimplementedError, A.StateError, A.ConcurrentModificationError]);\n" " _inherit(A.UnmodifiableListBase, A.ListBase);\n" " _inherit(A.CodeUnits, A.UnmodifiableListBase);\n" -" _inheritMany(A.Closure0Args, [A.nullFuture_closure, A._AsyncRun__scheduleImmediateJsOverride_internalCallback, A._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback, A._TimerImpl_internalCallback, A._TimerImpl\$periodic_closure, A.Future_Future\$microtask_closure, A.Future_Future\$delayed_closure, A._Future__addListener_closure, A._Future__prependListeners_closure, A._Future__chainCoreFuture_closure, A._Future__asyncCompleteWithValue_closure, A._Future__asyncCompleteErrorObject_closure, A._Future__propagateToListeners_handleWhenCompleteCallback, A._Future__propagateToListeners_handleValueCallback, A._Future__propagateToListeners_handleError, A._Future_timeout_closure, A.Stream_length_closure0, A.Stream_first_closure, A._StreamController__subscribe_closure, A._StreamController__recordCancel_complete, A._BufferingStreamSubscription_asFuture_closure, A._BufferingStreamSubscription_asFuture__closure, A._BufferingStreamSubscription__sendError_sendError, A._BufferingStreamSubscription__sendDone_sendDone, A._PendingEvents_schedule_closure, A._MultiStream_listen_closure, A._cancelAndValue_closure, A._CustomZone_bindCallback_closure, A._CustomZone_bindCallbackGuarded_closure, A._RootZone_bindCallback_closure, A._RootZone_bindCallbackGuarded_closure, A._rootHandleError_closure, A._Utf8Decoder__decoder_closure, A._Utf8Decoder__decoderNonfatal_closure, A.StreamQueue__ensureListening_closure0, A.BuildStatus_BuildStatus\$fromJson_closure0, A.BatchedStreamController__hasEventOrTimeOut_closure, A.BatchedStreamController__hasEventDuring_closure, A._readStreamBody_closure, A._readStreamBody_closure0, A.MediaType_MediaType\$parse_closure, A.Logger_Logger_closure, A.Highlighter_closure, A.Highlighter__writeFileStart_closure, A.Highlighter__writeMultilineHighlights_closure, A.Highlighter__writeMultilineHighlights_closure0, A.Highlighter__writeMultilineHighlights_closure1, A.Highlighter__writeMultilineHighlights_closure2, A.Highlighter__writeMultilineHighlights__closure, A.Highlighter__writeMultilineHighlights__closure0, A.Highlighter__writeHighlightedText_closure, A.Highlighter__writeIndicator_closure, A.Highlighter__writeIndicator_closure0, A.Highlighter__writeIndicator_closure1, A.Highlighter__writeSidebar_closure, A._Highlight_closure, A.SseClient_closure, A.SseClient__closure, A.SseClient__onOutgoingMessage_closure, A.main_closure, A.main__closure, A.main__closure0, A.main__closure1, A.main__closure4, A.main__closure8, A.DdcLibraryBundleRestarter__getSrcModuleLibraries_closure, A.RequireRestarter__reload_closure, A.RequireRestarter__reloadModule_closure, A._createScript_closure, A._createScript__closure, A._createScript__closure0, A.runMain_closure]);\n" +" _inheritMany(A.Closure0Args, [A.nullFuture_closure, A._AsyncRun__scheduleImmediateJsOverride_internalCallback, A._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback, A._TimerImpl_internalCallback, A.Future_Future\$microtask_closure, A.Future_Future\$delayed_closure, A._Future__addListener_closure, A._Future__prependListeners_closure, A._Future__chainCoreFuture_closure, A._Future__asyncCompleteWithValue_closure, A._Future__asyncCompleteErrorObject_closure, A._Future__propagateToListeners_handleWhenCompleteCallback, A._Future__propagateToListeners_handleValueCallback, A._Future__propagateToListeners_handleError, A._Future_timeout_closure, A.Stream_length_closure0, A.Stream_first_closure, A._StreamController__subscribe_closure, A._StreamController__recordCancel_complete, A._BufferingStreamSubscription_asFuture_closure, A._BufferingStreamSubscription_asFuture__closure, A._BufferingStreamSubscription__sendError_sendError, A._BufferingStreamSubscription__sendDone_sendDone, A._PendingEvents_schedule_closure, A._MultiStream_listen_closure, A._cancelAndValue_closure, A.Zone_bindCallback_closure, A.Zone_bindCallbackGuarded_closure, A._rootHandleUncaughtError_closure, A._Utf8Decoder__decoder_closure, A._Utf8Decoder__decoderNonfatal_closure, A.StreamQueue__ensureListening_closure0, A.BuildStatus_BuildStatus\$fromJson_closure0, A.BatchedStreamController__hasEventOrTimeOut_closure, A.BatchedStreamController__hasEventDuring_closure, A._readStreamBody_closure, A._readStreamBody_closure0, A.MediaType_MediaType\$parse_closure, A.Logger_Logger_closure, A.Highlighter_closure, A.Highlighter__writeFileStart_closure, A.Highlighter__writeMultilineHighlights_closure, A.Highlighter__writeMultilineHighlights_closure0, A.Highlighter__writeMultilineHighlights_closure1, A.Highlighter__writeMultilineHighlights_closure2, A.Highlighter__writeMultilineHighlights__closure, A.Highlighter__writeMultilineHighlights__closure0, A.Highlighter__writeHighlightedText_closure, A.Highlighter__writeIndicator_closure, A.Highlighter__writeIndicator_closure0, A.Highlighter__writeIndicator_closure1, A.Highlighter__writeSidebar_closure, A._Highlight_closure, A.SseClient_closure, A.SseClient__closure, A.SseClient__onOutgoingMessage_closure, A.main_closure, A.main__closure, A.main__closure0, A.main__closure1, A.main__closure4, A.main__closure8, A.DdcLibraryBundleRestarter__getSrcModuleLibraries_closure, A.RequireRestarter__reload_closure, A.RequireRestarter__reloadModule_closure, A._createScript_closure, A._createScript__closure, A._createScript__closure0, A.runMain_closure]);\n" " _inheritMany(A.EfficientLengthIterable, [A.ListIterable, A.EmptyIterable, A.LinkedHashMapKeysIterable, A.LinkedHashMapValuesIterable, A.LinkedHashMapEntriesIterable, A._HashMapKeyIterable]);\n" " _inheritMany(A.ListIterable, [A.SubListIterable, A.MappedListIterable, A.ReversedListIterable, A.ListQueue, A._JsonMapKeyIterable]);\n" " _inherit(A.EfficientLengthMappedIterable, A.MappedIterable);\n" @@ -22272,7 +21875,6 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _inheritMany(A._DelayedEvent, [A._DelayedData, A._DelayedError]);\n" " _inherit(A._MultiStreamController, A._AsyncStreamController);\n" " _inherit(A._MapStream, A._ForwardingStream);\n" -" _inheritMany(A._Zone, [A._CustomZone, A._RootZone]);\n" " _inherit(A._IdentityHashMap, A._HashMap);\n" " _inherit(A._SetBase, A.SetBase);\n" " _inherit(A._HashSet, A._SetBase);\n" @@ -22333,7 +21935,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " typeUniverse: {eC: new Map(), tR: {}, eT: {}, tPV: {}, sEA: []},\n" " mangledGlobalNames: {int: \"int\", double: \"double\", num: \"num\", String: \"String\", bool: \"bool\", Null: \"Null\", List: \"List\", Object: \"Object\", Map: \"Map\", JSObject: \"JSObject\"},\n" " mangledNames: {},\n" -" types: [\"~()\", \"Null()\", \"~(JSObject)\", \"Null(Object,StackTrace)\", \"~(@)\", \"JSObject()\", \"Future<~>()\", \"~(Object,StackTrace)\", \"Null(@)\", \"String(String)\", \"Object?(Object?)\", \"~(Object?)\", \"bool(_Highlight)\", \"Null(JSObject)\", \"~(~())\", \"int(Object?)\", \"@(@)\", \"Null(String)\", \"~(Object?,Object?)\", \"@()\", \"Null(JavaScriptFunction,JavaScriptFunction)\", \"bool()\", \"Future<~>(String)\", \"String(Match)\", \"bool(String)\", \"int()\", \"Null(JavaScriptFunction)\", \"int(@,@)\", \"bool(Object?,Object?)\", \"PersistentWebSocket(WebSocket)\", \"String(@)\", \"~(Zone,ZoneDelegate,Zone,Object,StackTrace)\", \"bool(Object?)\", \"Future<~>(WebSocketEvent)\", \"bool(String,String)\", \"int(String)\", \"Null(String,String[Object?])\", \"~(MultiStreamController>)\", \"~(List)\", \"MediaType()\", \"~(String,String)\", \"Null(@,StackTrace)\", \"Logger()\", \"~(int,@)\", \"String(String?)\", \"Null(~)\", \"String?()\", \"int(_Line)\", \"0&(String,int?)\", \"Object(_Line)\", \"Object(_Highlight)\", \"int(_Highlight,_Highlight)\", \"List<_Line>(MapEntry>)\", \"~(Object[StackTrace?])\", \"SourceSpanWithContext()\", \"@(String)\", \"~(String?)\", \"Future()\", \"@(@,String)\", \"JSObject(Object,StackTrace)\", \"JSObject(String[bool?])\", \"~(StreamSink<@>)\", \"~(List)\", \"Null(String,String)\", \"~(bool)\", \"HotReloadResponse(String,bool,String?)\", \"HotRestartResponse(String,bool,String?)\", \"Object?(~)\", \"bool(bool)\", \"List(String)\", \"int(String,String)\", \"Null(JavaScriptObject)\", \"JSObject()()\", \"bool(BuildStatus)\", \"0&()\", \"~(Zone?,ZoneDelegate?,Zone,Object,StackTrace)\", \"0^(Zone?,ZoneDelegate?,Zone,0^())\", \"0^(Zone?,ZoneDelegate?,Zone,0^(1^),1^)\", \"0^(Zone?,ZoneDelegate?,Zone,0^(1^,2^),1^,2^)\", \"0^()(Zone,ZoneDelegate,Zone,0^())\", \"0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))\", \"0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))\", \"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?)\", \"Map(DebugEvent)\", \"Null(~())\", \"0^(0^,0^)\", \"~(@,StackTrace)\"],\n" +" types: [\"~()\", \"Null()\", \"~(JSObject)\", \"Null(Object,StackTrace)\", \"~(@)\", \"JSObject()\", \"Future<~>()\", \"~(Object,StackTrace)\", \"Null(@)\", \"String(String)\", \"Object?(Object?)\", \"~(Object?)\", \"bool(_Highlight)\", \"Null(JSObject)\", \"~(~())\", \"int(Object?)\", \"@(@)\", \"~(Object?,Object?)\", \"@()\", \"Null(JavaScriptFunction,JavaScriptFunction)\", \"bool()\", \"Future<~>(String)\", \"String(Match)\", \"bool(String)\", \"int()\", \"Null(String)\", \"Null(JavaScriptFunction)\", \"int(@,@)\", \"bool(Object?,Object?)\", \"bool(BuildStatus)\", \"String(@)\", \"PersistentWebSocket(WebSocket)\", \"~(Zone,ZoneDelegate,Zone,Object,StackTrace)\", \"Future<~>(WebSocketEvent)\", \"bool(String,String)\", \"int(String)\", \"Null(String,String[Object?])\", \"~(MultiStreamController>)\", \"~(List)\", \"MediaType()\", \"~(String,String)\", \"bool(Object?)\", \"Logger()\", \"Null(~())\", \"String(String?)\", \"Null(~)\", \"String?()\", \"int(_Line)\", \"Null(@,StackTrace)\", \"Object(_Line)\", \"Object(_Highlight)\", \"int(_Highlight,_Highlight)\", \"~(StreamSink<@>)\", \"0&(String,int?)\", \"SourceSpanWithContext()\", \"~(int,@)\", \"~(String?)\", \"Future()\", \"~(Object[StackTrace?])\", \"@(String)\", \"JSObject(String[bool?])\", \"JSObject(Object,StackTrace)\", \"~(List)\", \"Null(String,String)\", \"~(bool)\", \"HotReloadResponse(String,bool,String?)\", \"HotRestartResponse(String,bool,String?)\", \"Object?(~)\", \"bool(bool)\", \"List(String)\", \"int(String,String)\", \"Null(JavaScriptObject)\", \"JSObject()()\", \"@(@,String)\", \"0&()\", \"Map(DebugEvent)\", \"~(@,StackTrace)\", \"0^(0^,0^)\", \"List<_Line>(MapEntry>)\"],\n" " interceptorsByTag: null,\n" " leafTags: null,\n" " arrayRti: Symbol(\"\$ti\"),\n" @@ -22341,7 +21943,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " \"2;\": (t1, t2) => o => o instanceof A._Record_2 && t1._is(o._0) && t2._is(o._1)\n" " }\n" " };\n" -" A._Universe_addRules(init.typeUniverse, JSON.parse('{\"JavaScriptFunction\":\"LegacyJavaScriptObject\",\"PlainJavaScriptObject\":\"LegacyJavaScriptObject\",\"UnknownJavaScriptObject\":\"LegacyJavaScriptObject\",\"NativeSharedArrayBuffer\":\"NativeByteBuffer\",\"JavaScriptObject\":{\"JSObject\":[]},\"JSArray\":{\"List\":[\"1\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"1\"],\"JSObject\":[],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"JSBool\":{\"bool\":[],\"TrustedGetRuntimeType\":[]},\"JSNull\":{\"Null\":[],\"TrustedGetRuntimeType\":[]},\"LegacyJavaScriptObject\":{\"JavaScriptObject\":[],\"JSObject\":[]},\"JSArraySafeToStringHook\":{\"SafeToStringHook\":[]},\"JSUnmodifiableArray\":{\"JSArray\":[\"1\"],\"List\":[\"1\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"1\"],\"JSObject\":[],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"ArrayIterator\":{\"Iterator\":[\"1\"]},\"JSNumber\":{\"double\":[],\"num\":[],\"Comparable\":[\"num\"]},\"JSInt\":{\"double\":[],\"int\":[],\"num\":[],\"Comparable\":[\"num\"],\"TrustedGetRuntimeType\":[]},\"JSNumNotInt\":{\"double\":[],\"num\":[],\"Comparable\":[\"num\"],\"TrustedGetRuntimeType\":[]},\"JSString\":{\"String\":[],\"Comparable\":[\"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\"},\"CastMap\":{\"MapBase\":[\"3\",\"4\"],\"Map\":[\"3\",\"4\"],\"MapBase.K\":\"3\",\"MapBase.V\":\"4\"},\"LateError\":{\"Error\":[]},\"CodeUnits\":{\"ListBase\":[\"int\"],\"UnmodifiableListMixin\":[\"int\"],\"List\":[\"int\"],\"EfficientLengthIterable\":[\"int\"],\"Iterable\":[\"int\"],\"ListBase.E\":\"int\",\"Iterable.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\"]},\"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\"},\"_Record_2\":{\"_Record2\":[],\"_Record\":[]},\"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\":[]},\"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\":[]},\"JsLinkedHashMap\":{\"MapBase\":[\"1\",\"2\"],\"LinkedHashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"LinkedHashMapKeysIterable\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"LinkedHashMapKeyIterator\":{\"Iterator\":[\"1\"]},\"LinkedHashMapValuesIterable\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"LinkedHashMapValueIterator\":{\"Iterator\":[\"1\"]},\"LinkedHashMapEntriesIterable\":{\"EfficientLengthIterable\":[\"MapEntry<1,2>\"],\"Iterable\":[\"MapEntry<1,2>\"],\"Iterable.E\":\"MapEntry<1,2>\"},\"LinkedHashMapEntryIterator\":{\"Iterator\":[\"MapEntry<1,2>\"]},\"JsIdentityLinkedHashMap\":{\"JsLinkedHashMap\":[\"1\",\"2\"],\"MapBase\":[\"1\",\"2\"],\"LinkedHashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"_Record2\":{\"_Record\":[]},\"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\":[],\"JSObject\":[],\"ByteBuffer\":[],\"TrustedGetRuntimeType\":[]},\"NativeArrayBuffer\":{\"NativeByteBuffer\":[],\"JavaScriptObject\":[],\"JSObject\":[],\"ByteBuffer\":[],\"TrustedGetRuntimeType\":[]},\"NativeTypedData\":{\"JavaScriptObject\":[],\"JSObject\":[]},\"_UnmodifiableNativeByteBufferView\":{\"ByteBuffer\":[]},\"NativeByteData\":{\"JavaScriptObject\":[],\"ByteData\":[],\"JSObject\":[],\"TrustedGetRuntimeType\":[]},\"NativeTypedArray\":{\"JavaScriptIndexingBehavior\":[\"1\"],\"JavaScriptObject\":[],\"JSObject\":[]},\"NativeTypedArrayOfDouble\":{\"ListBase\":[\"double\"],\"NativeTypedArray\":[\"double\"],\"List\":[\"double\"],\"JavaScriptIndexingBehavior\":[\"double\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"double\"],\"JSObject\":[],\"Iterable\":[\"double\"],\"FixedLengthListMixin\":[\"double\"]},\"NativeTypedArrayOfInt\":{\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"]},\"NativeFloat32List\":{\"Float32List\":[],\"ListBase\":[\"double\"],\"NativeTypedArray\":[\"double\"],\"List\":[\"double\"],\"JavaScriptIndexingBehavior\":[\"double\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"double\"],\"JSObject\":[],\"Iterable\":[\"double\"],\"FixedLengthListMixin\":[\"double\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"double\",\"Iterable.E\":\"double\",\"FixedLengthListMixin.E\":\"double\"},\"NativeFloat64List\":{\"Float64List\":[],\"ListBase\":[\"double\"],\"NativeTypedArray\":[\"double\"],\"List\":[\"double\"],\"JavaScriptIndexingBehavior\":[\"double\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"double\"],\"JSObject\":[],\"Iterable\":[\"double\"],\"FixedLengthListMixin\":[\"double\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"double\",\"Iterable.E\":\"double\",\"FixedLengthListMixin.E\":\"double\"},\"NativeInt16List\":{\"NativeTypedArrayOfInt\":[],\"Int16List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeInt32List\":{\"NativeTypedArrayOfInt\":[],\"Int32List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeInt8List\":{\"NativeTypedArrayOfInt\":[],\"Int8List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeUint16List\":{\"NativeTypedArrayOfInt\":[],\"Uint16List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeUint32List\":{\"NativeTypedArrayOfInt\":[],\"Uint32List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeUint8ClampedList\":{\"NativeTypedArrayOfInt\":[],\"Uint8ClampedList\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeUint8List\":{\"NativeTypedArrayOfInt\":[],\"Uint8List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"_Error\":{\"Error\":[]},\"_TypeError\":{\"TypeError\":[],\"Error\":[]},\"AsyncError\":{\"Error\":[]},\"MultiStreamController\":{\"StreamController\":[\"1\"],\"StreamSink\":[\"1\"]},\"_TimerImpl\":{\"Timer\":[]},\"_AsyncAwaitCompleter\":{\"Completer\":[\"1\"]},\"_Completer\":{\"Completer\":[\"1\"]},\"_AsyncCompleter\":{\"_Completer\":[\"1\"],\"Completer\":[\"1\"]},\"_SyncCompleter\":{\"_Completer\":[\"1\"],\"Completer\":[\"1\"]},\"_Future\":{\"Future\":[\"1\"]},\"StreamView\":{\"Stream\":[\"1\"]},\"_StreamController\":{\"StreamController\":[\"1\"],\"StreamSink\":[\"1\"],\"_StreamControllerLifecycle\":[\"1\"],\"_EventSink\":[\"1\"],\"_EventDispatch\":[\"1\"]},\"_AsyncStreamController\":{\"_AsyncStreamControllerDispatch\":[\"1\"],\"_StreamController\":[\"1\"],\"StreamController\":[\"1\"],\"StreamSink\":[\"1\"],\"_StreamControllerLifecycle\":[\"1\"],\"_EventSink\":[\"1\"],\"_EventDispatch\":[\"1\"]},\"_ControllerStream\":{\"_StreamImpl\":[\"1\"],\"Stream\":[\"1\"],\"Stream.T\":\"1\"},\"_ControllerSubscription\":{\"_BufferingStreamSubscription\":[\"1\"],\"StreamSubscription\":[\"1\"],\"_EventSink\":[\"1\"],\"_EventDispatch\":[\"1\"],\"_BufferingStreamSubscription.T\":\"1\"},\"_StreamSinkWrapper\":{\"StreamSink\":[\"1\"]},\"_BufferingStreamSubscription\":{\"StreamSubscription\":[\"1\"],\"_EventSink\":[\"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\"},\"_MultiStream\":{\"Stream\":[\"1\"],\"Stream.T\":\"1\"},\"_MultiStreamController\":{\"_AsyncStreamController\":[\"1\"],\"_AsyncStreamControllerDispatch\":[\"1\"],\"_StreamController\":[\"1\"],\"MultiStreamController\":[\"1\"],\"StreamController\":[\"1\"],\"StreamSink\":[\"1\"],\"_StreamControllerLifecycle\":[\"1\"],\"_EventSink\":[\"1\"],\"_EventDispatch\":[\"1\"]},\"_ForwardingStream\":{\"Stream\":[\"2\"]},\"_ForwardingStreamSubscription\":{\"_BufferingStreamSubscription\":[\"2\"],\"StreamSubscription\":[\"2\"],\"_EventSink\":[\"2\"],\"_EventDispatch\":[\"2\"],\"_BufferingStreamSubscription.T\":\"2\"},\"_MapStream\":{\"_ForwardingStream\":[\"1\",\"2\"],\"Stream\":[\"2\"],\"Stream.T\":\"2\"},\"_Zone\":{\"Zone\":[]},\"_CustomZone\":{\"_Zone\":[],\"Zone\":[]},\"_RootZone\":{\"_Zone\":[],\"Zone\":[]},\"_ZoneDelegate\":{\"ZoneDelegate\":[]},\"_ZoneSpecification\":{\"ZoneSpecification\":[]},\"_SplayTreeSetNode\":{\"_SplayTreeNode\":[\"1\",\"_SplayTreeSetNode<1>\"],\"_SplayTreeNode.K\":\"1\",\"_SplayTreeNode.1\":\"_SplayTreeSetNode<1>\"},\"_HashMap\":{\"MapBase\":[\"1\",\"2\"],\"HashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"_IdentityHashMap\":{\"_HashMap\":[\"1\",\"2\"],\"MapBase\":[\"1\",\"2\"],\"HashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"_HashMapKeyIterable\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"_HashMapKeyIterator\":{\"Iterator\":[\"1\"]},\"_LinkedCustomHashMap\":{\"JsLinkedHashMap\":[\"1\",\"2\"],\"MapBase\":[\"1\",\"2\"],\"LinkedHashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"_HashSet\":{\"SetBase\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"_HashSetIterator\":{\"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\"]},\"ListQueue\":{\"Queue\":[\"1\"],\"ListIterable\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"ListIterable.E\":\"1\",\"Iterable.E\":\"1\"},\"_ListQueueIterator\":{\"Iterator\":[\"1\"]},\"SetBase\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"]},\"_SetBase\":{\"SetBase\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"]},\"_SplayTreeIterator\":{\"Iterator\":[\"3\"]},\"_SplayTreeKeyIterator\":{\"_SplayTreeIterator\":[\"1\",\"2\",\"1\"],\"Iterator\":[\"1\"],\"_SplayTreeIterator.K\":\"1\",\"_SplayTreeIterator.T\":\"1\",\"_SplayTreeIterator.1\":\"2\"},\"SplayTreeSet\":{\"SetBase\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"_SplayTree\":[\"1\",\"_SplayTreeSetNode<1>\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\",\"_SplayTree.1\":\"_SplayTreeSetNode<1>\",\"_SplayTree.K\":\"1\"},\"Encoding\":{\"Codec\":[\"String\",\"List\"]},\"_JsonMap\":{\"MapBase\":[\"String\",\"@\"],\"Map\":[\"String\",\"@\"],\"MapBase.K\":\"String\",\"MapBase.V\":\"@\"},\"_JsonMapKeyIterable\":{\"ListIterable\":[\"String\"],\"EfficientLengthIterable\":[\"String\"],\"Iterable\":[\"String\"],\"ListIterable.E\":\"String\",\"Iterable.E\":\"String\"},\"AsciiCodec\":{\"Encoding\":[],\"Codec\":[\"String\",\"List\"]},\"_UnicodeSubsetEncoder\":{\"Converter\":[\"String\",\"List\"]},\"AsciiEncoder\":{\"Converter\":[\"String\",\"List\"]},\"_UnicodeSubsetDecoder\":{\"Converter\":[\"List\",\"String\"]},\"AsciiDecoder\":{\"Converter\":[\"List\",\"String\"]},\"Base64Codec\":{\"Codec\":[\"List\",\"String\"]},\"Base64Encoder\":{\"Converter\":[\"List\",\"String\"]},\"JsonUnsupportedObjectError\":{\"Error\":[]},\"JsonCyclicError\":{\"Error\":[]},\"JsonCodec\":{\"Codec\":[\"Object?\",\"String\"]},\"JsonEncoder\":{\"Converter\":[\"Object?\",\"String\"]},\"JsonDecoder\":{\"Converter\":[\"String\",\"Object?\"]},\"Latin1Codec\":{\"Encoding\":[],\"Codec\":[\"String\",\"List\"]},\"Latin1Encoder\":{\"Converter\":[\"String\",\"List\"]},\"Latin1Decoder\":{\"Converter\":[\"List\",\"String\"]},\"Utf8Codec\":{\"Encoding\":[],\"Codec\":[\"String\",\"List\"]},\"Utf8Encoder\":{\"Converter\":[\"String\",\"List\"]},\"Utf8Decoder\":{\"Converter\":[\"List\",\"String\"]},\"DateTime\":{\"Comparable\":[\"DateTime\"]},\"double\":{\"num\":[],\"Comparable\":[\"num\"]},\"Duration\":{\"Comparable\":[\"Duration\"]},\"int\":{\"num\":[],\"Comparable\":[\"num\"]},\"List\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"]},\"num\":{\"Comparable\":[\"num\"]},\"RegExpMatch\":{\"Match\":[]},\"String\":{\"Comparable\":[\"String\"],\"Pattern\":[]},\"AssertionError\":{\"Error\":[]},\"TypeError\":{\"Error\":[]},\"ArgumentError\":{\"Error\":[]},\"RangeError\":{\"Error\":[]},\"IndexError\":{\"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\":[]},\"NullRejectionException\":{\"Exception\":[]},\"ErrorResult\":{\"Result\":[\"0&\"]},\"ValueResult\":{\"Result\":[\"1\"]},\"_NextRequest\":{\"_EventRequest\":[\"1\"]},\"_HasNextRequest\":{\"_EventRequest\":[\"1\"]},\"CanonicalizedMap\":{\"Map\":[\"2\",\"3\"]},\"QueueList\":{\"ListBase\":[\"1\"],\"List\":[\"1\"],\"Queue\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"ListBase.E\":\"1\",\"QueueList.E\":\"1\",\"Iterable.E\":\"1\"},\"_CastQueueList\":{\"QueueList\":[\"2\"],\"ListBase\":[\"2\"],\"List\":[\"2\"],\"Queue\":[\"2\"],\"EfficientLengthIterable\":[\"2\"],\"Iterable\":[\"2\"],\"ListBase.E\":\"2\",\"QueueList.E\":\"2\",\"Iterable.E\":\"2\"},\"PersistentWebSocket\":{\"StreamChannelMixin\":[\"@\"]},\"SseSocketClient\":{\"SocketClient\":[]},\"WebSocketClient\":{\"SocketClient\":[]},\"RequestAbortedException\":{\"Exception\":[]},\"ByteStream\":{\"StreamView\":[\"List\"],\"Stream\":[\"List\"],\"Stream.T\":\"List\",\"StreamView.T\":\"List\"},\"ClientException\":{\"Exception\":[]},\"Request\":{\"BaseRequest\":[]},\"StreamedResponseV2\":{\"StreamedResponse\":[]},\"CaseInsensitiveMap\":{\"CanonicalizedMap\":[\"String\",\"String\",\"1\"],\"Map\":[\"String\",\"1\"],\"CanonicalizedMap.K\":\"String\",\"CanonicalizedMap.V\":\"1\",\"CanonicalizedMap.C\":\"String\"},\"Level\":{\"Comparable\":[\"Level\"]},\"PathException\":{\"Exception\":[]},\"PosixStyle\":{\"InternalStyle\":[]},\"UrlStyle\":{\"InternalStyle\":[]},\"WindowsStyle\":{\"InternalStyle\":[]},\"FileLocation\":{\"SourceLocation\":[],\"Comparable\":[\"SourceLocation\"]},\"_FileSpan\":{\"SourceSpanWithContext\":[],\"SourceSpan\":[],\"Comparable\":[\"SourceSpan\"]},\"SourceLocation\":{\"Comparable\":[\"SourceLocation\"]},\"SourceLocationMixin\":{\"SourceLocation\":[],\"Comparable\":[\"SourceLocation\"]},\"SourceSpan\":{\"Comparable\":[\"SourceSpan\"]},\"SourceSpanBase\":{\"SourceSpan\":[],\"Comparable\":[\"SourceSpan\"]},\"SourceSpanException\":{\"Exception\":[]},\"SourceSpanFormatException\":{\"FormatException\":[],\"Exception\":[]},\"SourceSpanMixin\":{\"SourceSpan\":[],\"Comparable\":[\"SourceSpan\"]},\"SourceSpanWithContext\":{\"SourceSpan\":[],\"Comparable\":[\"SourceSpan\"]},\"SseClient\":{\"StreamChannelMixin\":[\"String?\"]},\"StringScannerException\":{\"FormatException\":[],\"Exception\":[]},\"_EventStream\":{\"Stream\":[\"1\"],\"Stream.T\":\"1\"},\"_EventStreamSubscription\":{\"StreamSubscription\":[\"1\"]},\"BrowserWebSocket\":{\"WebSocket\":[]},\"TextDataReceived\":{\"WebSocketEvent\":[]},\"BinaryDataReceived\":{\"WebSocketEvent\":[]},\"CloseReceived\":{\"WebSocketEvent\":[]},\"WebSocketException\":{\"Exception\":[]},\"WebSocketConnectionClosed\":{\"Exception\":[]},\"DdcLibraryBundleRestarter\":{\"TwoPhaseRestarter\":[],\"Restarter\":[]},\"DdcRestarter\":{\"Restarter\":[]},\"RequireRestarter\":{\"Restarter\":[]},\"HotReloadFailedException\":{\"Exception\":[]},\"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\"]}}'));\n" +" A._Universe_addRules(init.typeUniverse, JSON.parse('{\"JavaScriptFunction\":\"LegacyJavaScriptObject\",\"PlainJavaScriptObject\":\"LegacyJavaScriptObject\",\"UnknownJavaScriptObject\":\"LegacyJavaScriptObject\",\"NativeSharedArrayBuffer\":\"NativeByteBuffer\",\"JavaScriptObject\":{\"JSObject\":[]},\"JSArray\":{\"List\":[\"1\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"1\"],\"JSObject\":[],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"JSBool\":{\"bool\":[],\"TrustedGetRuntimeType\":[]},\"JSNull\":{\"Null\":[],\"TrustedGetRuntimeType\":[]},\"LegacyJavaScriptObject\":{\"JavaScriptObject\":[],\"JSObject\":[]},\"JSArraySafeToStringHook\":{\"SafeToStringHook\":[]},\"JSUnmodifiableArray\":{\"JSArray\":[\"1\"],\"List\":[\"1\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"1\"],\"JSObject\":[],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"ArrayIterator\":{\"Iterator\":[\"1\"]},\"JSNumber\":{\"double\":[],\"num\":[],\"Comparable\":[\"num\"]},\"JSInt\":{\"double\":[],\"int\":[],\"num\":[],\"Comparable\":[\"num\"],\"TrustedGetRuntimeType\":[]},\"JSNumNotInt\":{\"double\":[],\"num\":[],\"Comparable\":[\"num\"],\"TrustedGetRuntimeType\":[]},\"JSString\":{\"String\":[],\"Comparable\":[\"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\"},\"CastMap\":{\"MapBase\":[\"3\",\"4\"],\"Map\":[\"3\",\"4\"],\"MapBase.K\":\"3\",\"MapBase.V\":\"4\"},\"LateError\":{\"Error\":[]},\"CodeUnits\":{\"ListBase\":[\"int\"],\"UnmodifiableListMixin\":[\"int\"],\"List\":[\"int\"],\"EfficientLengthIterable\":[\"int\"],\"Iterable\":[\"int\"],\"ListBase.E\":\"int\",\"Iterable.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\"]},\"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\"},\"_Record_2\":{\"_Record2\":[],\"_Record\":[]},\"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\":[]},\"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\":[]},\"JsLinkedHashMap\":{\"MapBase\":[\"1\",\"2\"],\"LinkedHashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"LinkedHashMapKeysIterable\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"LinkedHashMapKeyIterator\":{\"Iterator\":[\"1\"]},\"LinkedHashMapValuesIterable\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"LinkedHashMapValueIterator\":{\"Iterator\":[\"1\"]},\"LinkedHashMapEntriesIterable\":{\"EfficientLengthIterable\":[\"MapEntry<1,2>\"],\"Iterable\":[\"MapEntry<1,2>\"],\"Iterable.E\":\"MapEntry<1,2>\"},\"LinkedHashMapEntryIterator\":{\"Iterator\":[\"MapEntry<1,2>\"]},\"JsIdentityLinkedHashMap\":{\"JsLinkedHashMap\":[\"1\",\"2\"],\"MapBase\":[\"1\",\"2\"],\"LinkedHashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"_Record2\":{\"_Record\":[]},\"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\":[],\"JSObject\":[],\"ByteBuffer\":[],\"TrustedGetRuntimeType\":[]},\"NativeArrayBuffer\":{\"NativeByteBuffer\":[],\"JavaScriptObject\":[],\"JSObject\":[],\"ByteBuffer\":[],\"TrustedGetRuntimeType\":[]},\"NativeTypedData\":{\"JavaScriptObject\":[],\"JSObject\":[]},\"_UnmodifiableNativeByteBufferView\":{\"ByteBuffer\":[]},\"NativeByteData\":{\"JavaScriptObject\":[],\"ByteData\":[],\"JSObject\":[],\"TrustedGetRuntimeType\":[]},\"NativeTypedArray\":{\"JavaScriptIndexingBehavior\":[\"1\"],\"JavaScriptObject\":[],\"JSObject\":[]},\"NativeTypedArrayOfDouble\":{\"ListBase\":[\"double\"],\"NativeTypedArray\":[\"double\"],\"List\":[\"double\"],\"JavaScriptIndexingBehavior\":[\"double\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"double\"],\"JSObject\":[],\"Iterable\":[\"double\"],\"FixedLengthListMixin\":[\"double\"]},\"NativeTypedArrayOfInt\":{\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"]},\"NativeFloat32List\":{\"Float32List\":[],\"ListBase\":[\"double\"],\"NativeTypedArray\":[\"double\"],\"List\":[\"double\"],\"JavaScriptIndexingBehavior\":[\"double\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"double\"],\"JSObject\":[],\"Iterable\":[\"double\"],\"FixedLengthListMixin\":[\"double\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"double\",\"Iterable.E\":\"double\",\"FixedLengthListMixin.E\":\"double\"},\"NativeFloat64List\":{\"Float64List\":[],\"ListBase\":[\"double\"],\"NativeTypedArray\":[\"double\"],\"List\":[\"double\"],\"JavaScriptIndexingBehavior\":[\"double\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"double\"],\"JSObject\":[],\"Iterable\":[\"double\"],\"FixedLengthListMixin\":[\"double\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"double\",\"Iterable.E\":\"double\",\"FixedLengthListMixin.E\":\"double\"},\"NativeInt16List\":{\"NativeTypedArrayOfInt\":[],\"Int16List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeInt32List\":{\"NativeTypedArrayOfInt\":[],\"Int32List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeInt8List\":{\"NativeTypedArrayOfInt\":[],\"Int8List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeUint16List\":{\"NativeTypedArrayOfInt\":[],\"Uint16List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeUint32List\":{\"NativeTypedArrayOfInt\":[],\"Uint32List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeUint8ClampedList\":{\"NativeTypedArrayOfInt\":[],\"Uint8ClampedList\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"NativeUint8List\":{\"NativeTypedArrayOfInt\":[],\"Uint8List\":[],\"ListBase\":[\"int\"],\"NativeTypedArray\":[\"int\"],\"List\":[\"int\"],\"JavaScriptIndexingBehavior\":[\"int\"],\"JavaScriptObject\":[],\"EfficientLengthIterable\":[\"int\"],\"JSObject\":[],\"Iterable\":[\"int\"],\"FixedLengthListMixin\":[\"int\"],\"TrustedGetRuntimeType\":[],\"ListBase.E\":\"int\",\"Iterable.E\":\"int\",\"FixedLengthListMixin.E\":\"int\"},\"_Error\":{\"Error\":[]},\"_TypeError\":{\"TypeError\":[],\"Error\":[]},\"AsyncError\":{\"Error\":[]},\"MultiStreamController\":{\"StreamController\":[\"1\"],\"StreamSink\":[\"1\"]},\"_TimerImpl\":{\"Timer\":[]},\"_AsyncAwaitCompleter\":{\"Completer\":[\"1\"]},\"_Completer\":{\"Completer\":[\"1\"]},\"_AsyncCompleter\":{\"_Completer\":[\"1\"],\"Completer\":[\"1\"]},\"_SyncCompleter\":{\"_Completer\":[\"1\"],\"Completer\":[\"1\"]},\"_Future\":{\"Future\":[\"1\"]},\"StreamView\":{\"Stream\":[\"1\"]},\"_StreamController\":{\"StreamController\":[\"1\"],\"StreamSink\":[\"1\"],\"_StreamControllerLifecycle\":[\"1\"],\"_EventSink\":[\"1\"],\"_EventDispatch\":[\"1\"]},\"_AsyncStreamController\":{\"_AsyncStreamControllerDispatch\":[\"1\"],\"_StreamController\":[\"1\"],\"StreamController\":[\"1\"],\"StreamSink\":[\"1\"],\"_StreamControllerLifecycle\":[\"1\"],\"_EventSink\":[\"1\"],\"_EventDispatch\":[\"1\"]},\"_ControllerStream\":{\"_StreamImpl\":[\"1\"],\"Stream\":[\"1\"],\"Stream.T\":\"1\"},\"_ControllerSubscription\":{\"_BufferingStreamSubscription\":[\"1\"],\"StreamSubscription\":[\"1\"],\"_EventSink\":[\"1\"],\"_EventDispatch\":[\"1\"],\"_BufferingStreamSubscription.T\":\"1\"},\"_StreamSinkWrapper\":{\"StreamSink\":[\"1\"]},\"_BufferingStreamSubscription\":{\"StreamSubscription\":[\"1\"],\"_EventSink\":[\"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\"},\"_MultiStream\":{\"Stream\":[\"1\"],\"Stream.T\":\"1\"},\"_MultiStreamController\":{\"_AsyncStreamController\":[\"1\"],\"_AsyncStreamControllerDispatch\":[\"1\"],\"_StreamController\":[\"1\"],\"MultiStreamController\":[\"1\"],\"StreamController\":[\"1\"],\"StreamSink\":[\"1\"],\"_StreamControllerLifecycle\":[\"1\"],\"_EventSink\":[\"1\"],\"_EventDispatch\":[\"1\"]},\"_ForwardingStream\":{\"Stream\":[\"2\"]},\"_ForwardingStreamSubscription\":{\"_BufferingStreamSubscription\":[\"2\"],\"StreamSubscription\":[\"2\"],\"_EventSink\":[\"2\"],\"_EventDispatch\":[\"2\"],\"_BufferingStreamSubscription.T\":\"2\"},\"_MapStream\":{\"_ForwardingStream\":[\"1\",\"2\"],\"Stream\":[\"2\"],\"Stream.T\":\"2\"},\"_SplayTreeSetNode\":{\"_SplayTreeNode\":[\"1\",\"_SplayTreeSetNode<1>\"],\"_SplayTreeNode.K\":\"1\",\"_SplayTreeNode.1\":\"_SplayTreeSetNode<1>\"},\"_HashMap\":{\"MapBase\":[\"1\",\"2\"],\"HashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"_IdentityHashMap\":{\"_HashMap\":[\"1\",\"2\"],\"MapBase\":[\"1\",\"2\"],\"HashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"_HashMapKeyIterable\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"_HashMapKeyIterator\":{\"Iterator\":[\"1\"]},\"_LinkedCustomHashMap\":{\"JsLinkedHashMap\":[\"1\",\"2\"],\"MapBase\":[\"1\",\"2\"],\"LinkedHashMap\":[\"1\",\"2\"],\"Map\":[\"1\",\"2\"],\"MapBase.K\":\"1\",\"MapBase.V\":\"2\"},\"_HashSet\":{\"SetBase\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\"},\"_HashSetIterator\":{\"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\"]},\"ListQueue\":{\"Queue\":[\"1\"],\"ListIterable\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"ListIterable.E\":\"1\",\"Iterable.E\":\"1\"},\"_ListQueueIterator\":{\"Iterator\":[\"1\"]},\"SetBase\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"]},\"_SetBase\":{\"SetBase\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"]},\"_SplayTreeIterator\":{\"Iterator\":[\"3\"]},\"_SplayTreeKeyIterator\":{\"_SplayTreeIterator\":[\"1\",\"2\",\"1\"],\"Iterator\":[\"1\"],\"_SplayTreeIterator.K\":\"1\",\"_SplayTreeIterator.T\":\"1\",\"_SplayTreeIterator.1\":\"2\"},\"SplayTreeSet\":{\"SetBase\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"_SplayTree\":[\"1\",\"_SplayTreeSetNode<1>\"],\"Iterable\":[\"1\"],\"Iterable.E\":\"1\",\"_SplayTree.1\":\"_SplayTreeSetNode<1>\",\"_SplayTree.K\":\"1\"},\"Encoding\":{\"Codec\":[\"String\",\"List\"]},\"_JsonMap\":{\"MapBase\":[\"String\",\"@\"],\"Map\":[\"String\",\"@\"],\"MapBase.K\":\"String\",\"MapBase.V\":\"@\"},\"_JsonMapKeyIterable\":{\"ListIterable\":[\"String\"],\"EfficientLengthIterable\":[\"String\"],\"Iterable\":[\"String\"],\"ListIterable.E\":\"String\",\"Iterable.E\":\"String\"},\"AsciiCodec\":{\"Encoding\":[],\"Codec\":[\"String\",\"List\"]},\"_UnicodeSubsetEncoder\":{\"Converter\":[\"String\",\"List\"]},\"AsciiEncoder\":{\"Converter\":[\"String\",\"List\"]},\"_UnicodeSubsetDecoder\":{\"Converter\":[\"List\",\"String\"]},\"AsciiDecoder\":{\"Converter\":[\"List\",\"String\"]},\"Base64Codec\":{\"Codec\":[\"List\",\"String\"]},\"Base64Encoder\":{\"Converter\":[\"List\",\"String\"]},\"JsonUnsupportedObjectError\":{\"Error\":[]},\"JsonCyclicError\":{\"Error\":[]},\"JsonCodec\":{\"Codec\":[\"Object?\",\"String\"]},\"JsonEncoder\":{\"Converter\":[\"Object?\",\"String\"]},\"JsonDecoder\":{\"Converter\":[\"String\",\"Object?\"]},\"Latin1Codec\":{\"Encoding\":[],\"Codec\":[\"String\",\"List\"]},\"Latin1Encoder\":{\"Converter\":[\"String\",\"List\"]},\"Latin1Decoder\":{\"Converter\":[\"List\",\"String\"]},\"Utf8Codec\":{\"Encoding\":[],\"Codec\":[\"String\",\"List\"]},\"Utf8Encoder\":{\"Converter\":[\"String\",\"List\"]},\"Utf8Decoder\":{\"Converter\":[\"List\",\"String\"]},\"DateTime\":{\"Comparable\":[\"DateTime\"]},\"double\":{\"num\":[],\"Comparable\":[\"num\"]},\"Duration\":{\"Comparable\":[\"Duration\"]},\"int\":{\"num\":[],\"Comparable\":[\"num\"]},\"List\":{\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"]},\"num\":{\"Comparable\":[\"num\"]},\"RegExpMatch\":{\"Match\":[]},\"String\":{\"Comparable\":[\"String\"],\"Pattern\":[]},\"AssertionError\":{\"Error\":[]},\"TypeError\":{\"Error\":[]},\"ArgumentError\":{\"Error\":[]},\"RangeError\":{\"Error\":[]},\"IndexError\":{\"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\":[]},\"NullRejectionException\":{\"Exception\":[]},\"ErrorResult\":{\"Result\":[\"0&\"]},\"ValueResult\":{\"Result\":[\"1\"]},\"_NextRequest\":{\"_EventRequest\":[\"1\"]},\"_HasNextRequest\":{\"_EventRequest\":[\"1\"]},\"CanonicalizedMap\":{\"Map\":[\"2\",\"3\"]},\"QueueList\":{\"ListBase\":[\"1\"],\"List\":[\"1\"],\"Queue\":[\"1\"],\"EfficientLengthIterable\":[\"1\"],\"Iterable\":[\"1\"],\"ListBase.E\":\"1\",\"QueueList.E\":\"1\",\"Iterable.E\":\"1\"},\"_CastQueueList\":{\"QueueList\":[\"2\"],\"ListBase\":[\"2\"],\"List\":[\"2\"],\"Queue\":[\"2\"],\"EfficientLengthIterable\":[\"2\"],\"Iterable\":[\"2\"],\"ListBase.E\":\"2\",\"QueueList.E\":\"2\",\"Iterable.E\":\"2\"},\"PersistentWebSocket\":{\"StreamChannelMixin\":[\"@\"]},\"SseSocketClient\":{\"SocketClient\":[]},\"WebSocketClient\":{\"SocketClient\":[]},\"RequestAbortedException\":{\"Exception\":[]},\"ByteStream\":{\"StreamView\":[\"List\"],\"Stream\":[\"List\"],\"Stream.T\":\"List\",\"StreamView.T\":\"List\"},\"ClientException\":{\"Exception\":[]},\"Request\":{\"BaseRequest\":[]},\"StreamedResponseV2\":{\"StreamedResponse\":[]},\"CaseInsensitiveMap\":{\"CanonicalizedMap\":[\"String\",\"String\",\"1\"],\"Map\":[\"String\",\"1\"],\"CanonicalizedMap.K\":\"String\",\"CanonicalizedMap.V\":\"1\",\"CanonicalizedMap.C\":\"String\"},\"Level\":{\"Comparable\":[\"Level\"]},\"PathException\":{\"Exception\":[]},\"PosixStyle\":{\"InternalStyle\":[]},\"UrlStyle\":{\"InternalStyle\":[]},\"WindowsStyle\":{\"InternalStyle\":[]},\"FileLocation\":{\"SourceLocation\":[],\"Comparable\":[\"SourceLocation\"]},\"_FileSpan\":{\"SourceSpanWithContext\":[],\"SourceSpan\":[],\"Comparable\":[\"SourceSpan\"]},\"SourceLocation\":{\"Comparable\":[\"SourceLocation\"]},\"SourceLocationMixin\":{\"SourceLocation\":[],\"Comparable\":[\"SourceLocation\"]},\"SourceSpan\":{\"Comparable\":[\"SourceSpan\"]},\"SourceSpanBase\":{\"SourceSpan\":[],\"Comparable\":[\"SourceSpan\"]},\"SourceSpanException\":{\"Exception\":[]},\"SourceSpanFormatException\":{\"FormatException\":[],\"Exception\":[]},\"SourceSpanMixin\":{\"SourceSpan\":[],\"Comparable\":[\"SourceSpan\"]},\"SourceSpanWithContext\":{\"SourceSpan\":[],\"Comparable\":[\"SourceSpan\"]},\"SseClient\":{\"StreamChannelMixin\":[\"String?\"]},\"StringScannerException\":{\"FormatException\":[],\"Exception\":[]},\"_EventStream\":{\"Stream\":[\"1\"],\"Stream.T\":\"1\"},\"_EventStreamSubscription\":{\"StreamSubscription\":[\"1\"]},\"BrowserWebSocket\":{\"WebSocket\":[]},\"TextDataReceived\":{\"WebSocketEvent\":[]},\"BinaryDataReceived\":{\"WebSocketEvent\":[]},\"CloseReceived\":{\"WebSocketEvent\":[]},\"WebSocketException\":{\"Exception\":[]},\"WebSocketConnectionClosed\":{\"Exception\":[]},\"DdcLibraryBundleRestarter\":{\"TwoPhaseRestarter\":[],\"Restarter\":[]},\"DdcRestarter\":{\"Restarter\":[]},\"RequireRestarter\":{\"Restarter\":[]},\"HotReloadFailedException\":{\"Exception\":[]},\"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\"]}}'));\n" " A._Universe_addErasedTypes(init.typeUniverse, JSON.parse('{\"UnmodifiableListBase\":1,\"__CastListBase__CastIterableBase_ListMixin\":2,\"NativeTypedArray\":1,\"_DelayedEvent\":1,\"_SetBase\":1,\"_SplayTreeSet__SplayTree_Iterable\":1,\"_SplayTreeSet__SplayTree_Iterable_SetMixin\":1,\"_QueueList_Object_ListMixin\":1,\"StreamChannelMixin\":1}'));\n" " var string\$ = {\n" " x00_____: \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\u03f6\\x00\\u0404\\u03f4 \\u03f4\\u03f6\\u01f6\\u01f6\\u03f6\\u03fc\\u01f4\\u03ff\\u03ff\\u0584\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u05d4\\u01f4\\x00\\u01f4\\x00\\u0504\\u05c4\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u0400\\x00\\u0400\\u0200\\u03f7\\u0200\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u03ff\\u0200\\u0200\\u0200\\u03f7\\x00\",\n" @@ -22360,6 +21962,8 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " var type\$ = (function rtii() {\n" " var findType = A.findType;\n" " return {\n" +" \$env_1_1_dynamic: findType(\"@<@>\"),\n" +" \$env_1_1_void: findType(\"@<~>\"),\n" " AsyncError: findType(\"AsyncError\"),\n" " BatchedStreamController_DebugEvent: findType(\"BatchedStreamController\"),\n" " BrowserWebSocket: findType(\"BrowserWebSocket\"),\n" @@ -22442,7 +22046,6 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " StreamedResponse: findType(\"StreamedResponse\"),\n" " String: findType(\"String\"),\n" " String_Function_Match: findType(\"String(Match)\"),\n" -" Timer: findType(\"Timer\"),\n" " TrustedGetRuntimeType: findType(\"TrustedGetRuntimeType\"),\n" " TwoPhaseRestarter: findType(\"TwoPhaseRestarter\"),\n" " TypeError: findType(\"TypeError\"),\n" @@ -22456,7 +22059,6 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " WebSocket: findType(\"WebSocket\"),\n" " WebSocketEvent: findType(\"WebSocketEvent\"),\n" " WhereTypeIterable_String: findType(\"WhereTypeIterable\"),\n" -" Zone: findType(\"Zone\"),\n" " _AsyncCompleter_BrowserWebSocket: findType(\"_AsyncCompleter\"),\n" " _AsyncCompleter_PoolResource: findType(\"_AsyncCompleter\"),\n" " _AsyncCompleter_String: findType(\"_AsyncCompleter\"),\n" @@ -22481,7 +22083,6 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " _MultiStream_List_int: findType(\"_MultiStream>\"),\n" " _StreamControllerAddStreamState_nullable_Object: findType(\"_StreamControllerAddStreamState\"),\n" " _SyncCompleter_PoolResource: findType(\"_SyncCompleter\"),\n" -" _ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_Object_StackTrace: findType(\"_ZoneFunction<~(Zone,ZoneDelegate,Zone,Object,StackTrace)>\"),\n" " bool: findType(\"bool\"),\n" " bool_Function_Object: findType(\"bool(Object)\"),\n" " bool_Function__Highlight: findType(\"bool(_Highlight)\"),\n" @@ -22498,15 +22099,11 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " nullable_List_dynamic: findType(\"List<@>?\"),\n" " nullable_Map_String_dynamic: findType(\"Map?\"),\n" " nullable_Map_dynamic_dynamic: findType(\"Map<@,@>?\"),\n" -" nullable_Map_of_nullable_Object_and_nullable_Object: findType(\"Map?\"),\n" " nullable_Object: findType(\"Object?\"),\n" " nullable_Result_DebugEvent: findType(\"Result?\"),\n" " nullable_StackTrace: findType(\"StackTrace?\"),\n" " nullable_String: findType(\"String?\"),\n" " nullable_String_Function_Match: findType(\"String(Match)?\"),\n" -" nullable_Zone: findType(\"Zone?\"),\n" -" nullable_ZoneDelegate: findType(\"ZoneDelegate?\"),\n" -" nullable_ZoneSpecification: findType(\"ZoneSpecification?\"),\n" " nullable__DelayedEvent_dynamic: findType(\"_DelayedEvent<@>?\"),\n" " nullable__FutureListener_dynamic_dynamic: findType(\"_FutureListener<@,@>?\"),\n" " nullable__Highlight: findType(\"_Highlight?\"),\n" @@ -22523,7 +22120,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " void_Function_Object: findType(\"~(Object)\"),\n" " void_Function_Object_StackTrace: findType(\"~(Object,StackTrace)\"),\n" " void_Function_String_dynamic: findType(\"~(String,@)\"),\n" -" void_Function_Timer: findType(\"~(Timer)\")\n" +" void_Function_int_dynamic: findType(\"~(int,@)\")\n" " };\n" " })();\n" " (function constants() {\n" @@ -22682,7 +22279,6 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " B.C_Uuid = new A.Uuid();\n" " B.C__DelayedDone = new A._DelayedDone();\n" " B.C__JSRandom = new A._JSRandom();\n" -" B.C__RootZone = new A._RootZone();\n" " B.Duration_0 = new A.Duration(0);\n" " B.Duration_5000000 = new A.Duration(5000000);\n" " B.JsonDecoder_null = new A.JsonDecoder(null);\n" @@ -22718,20 +22314,8 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " B.Type_Uint8ClampedList_04U = A.typeLiteral(\"Uint8ClampedList\");\n" " B.Type_Uint8List_8Eb = A.typeLiteral(\"Uint8List\");\n" " B.Utf8Decoder_false = new A.Utf8Decoder(false);\n" +" B.Zone_jYP = new A.Zone(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);\n" " B._StringStackTrace_OdL = new A._StringStackTrace(\"\");\n" -" B._ZoneFunction_KjJ = new A._ZoneFunction(B.C__RootZone, A.async___rootHandleUncaughtError\$closure(), type\$._ZoneFunction_of_void_Function_Zone_ZoneDelegate_Zone_Object_StackTrace);\n" -" B._ZoneFunction_PAY = new A._ZoneFunction(B.C__RootZone, A.async___rootCreatePeriodicTimer\$closure(), A.findType(\"_ZoneFunction\"));\n" -" B._ZoneFunction_Xkh = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterUnaryCallback\$closure(), A.findType(\"_ZoneFunction<0^(1^)(Zone,ZoneDelegate,Zone,0^(1^))>\"));\n" -" B._ZoneFunction__RootZone__rootCreateTimer = new A._ZoneFunction(B.C__RootZone, A.async___rootCreateTimer\$closure(), A.findType(\"_ZoneFunction\"));\n" -" B._ZoneFunction__RootZone__rootErrorCallback = new A._ZoneFunction(B.C__RootZone, A.async___rootErrorCallback\$closure(), A.findType(\"_ZoneFunction\"));\n" -" B._ZoneFunction__RootZone__rootFork = new A._ZoneFunction(B.C__RootZone, A.async___rootFork\$closure(), A.findType(\"_ZoneFunction?)>\"));\n" -" B._ZoneFunction__RootZone__rootPrint = new A._ZoneFunction(B.C__RootZone, A.async___rootPrint\$closure(), A.findType(\"_ZoneFunction<~(Zone,ZoneDelegate,Zone,String)>\"));\n" -" B._ZoneFunction__RootZone__rootRegisterCallback = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterCallback\$closure(), A.findType(\"_ZoneFunction<0^()(Zone,ZoneDelegate,Zone,0^())>\"));\n" -" B._ZoneFunction__RootZone__rootRun = new A._ZoneFunction(B.C__RootZone, A.async___rootRun\$closure(), A.findType(\"_ZoneFunction<0^(Zone,ZoneDelegate,Zone,0^())>\"));\n" -" 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^)>\"));\n" -" B._ZoneFunction__RootZone__rootRunUnary = new A._ZoneFunction(B.C__RootZone, A.async___rootRunUnary\$closure(), A.findType(\"_ZoneFunction<0^(Zone,ZoneDelegate,Zone,0^(1^),1^)>\"));\n" -" B._ZoneFunction__RootZone__rootScheduleMicrotask = new A._ZoneFunction(B.C__RootZone, A.async___rootScheduleMicrotask\$closure(), A.findType(\"_ZoneFunction<~(Zone,ZoneDelegate,Zone,~())>\"));\n" -" B._ZoneFunction_e9o = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterBinaryCallback\$closure(), A.findType(\"_ZoneFunction<0^(1^,2^)(Zone,ZoneDelegate,Zone,0^(1^,2^))>\"));\n" " })();\n" " (function staticFields() {\n" " \$._JS_INTEROP_INTERCEPTOR_TAG = null;\n" @@ -22751,8 +22335,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " \$._lastCallback = null;\n" " \$._lastPriorityCallback = null;\n" " \$._isInCallbackLoop = false;\n" -" \$.Zone__current = B.C__RootZone;\n" -" \$._RootZone__rootDelegate = null;\n" +" \$.Zone__current = B.Zone_jYP;\n" " \$.Uri__cachedBaseString = \"\";\n" " \$.Uri__cachedBaseUri = null;\n" " \$.LogRecord__nextNumber = 0;\n" @@ -22765,7 +22348,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " var _lazyFinal = hunkHelpers.lazyFinal;\n" " _lazyFinal(\$, \"DART_CLOSURE_PROPERTY_NAME\", \"\$get\$DART_CLOSURE_PROPERTY_NAME\", () => A.getIsolateAffinityTag(\"_\$dart_dartClosure\"));\n" " _lazyFinal(\$, \"DART_CLOSURE_DART_JSINTEROP_PROPERTY_NAME\", \"\$get\$DART_CLOSURE_DART_JSINTEROP_PROPERTY_NAME\", () => A.getIsolateAffinityTag(\"_\$dart_dartClosure_dartJSInterop\"));\n" -" _lazyFinal(\$, \"nullFuture\", \"\$get\$nullFuture\", () => B.C__RootZone.run\$1\$1(new A.nullFuture_closure(), type\$.Future_void));\n" +" _lazyFinal(\$, \"nullFuture\", \"\$get\$nullFuture\", () => B.Zone_jYP.run\$1\$1(new A.nullFuture_closure(), type\$.Future_void));\n" " _lazyFinal(\$, \"_safeToStringHooks\", \"\$get\$_safeToStringHooks\", () => A._setArrayType([new J.JSArraySafeToStringHook()], A.findType(\"JSArray\")));\n" " _lazyFinal(\$, \"TypeErrorDecoder_noSuchMethodPattern\", \"\$get\$TypeErrorDecoder_noSuchMethodPattern\", () => A.TypeErrorDecoder_extractPattern(A.TypeErrorDecoder_provokeCallErrorOn({\n" " toString: function() {\n" @@ -22813,10 +22396,7 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " }()));\n" " _lazyFinal(\$, \"_AsyncRun__scheduleImmediateClosure\", \"\$get\$_AsyncRun__scheduleImmediateClosure\", () => A._AsyncRun__initializeScheduleImmediate());\n" " _lazyFinal(\$, \"Future__nullFuture\", \"\$get\$Future__nullFuture\", () => \$.\$get\$nullFuture());\n" -" _lazyFinal(\$, \"_RootZone__rootMap\", \"\$get\$_RootZone__rootMap\", () => {\n" -" var t1 = type\$.dynamic;\n" -" return A.HashMap_HashMap(null, null, t1, t1);\n" -" });\n" +" _lazyFinal(\$, \"_rootDelegate\", \"\$get\$_rootDelegate\", () => A.ZoneDelegate\$_());\n" " _lazyFinal(\$, \"_Utf8Decoder__reusableBuffer\", \"\$get\$_Utf8Decoder__reusableBuffer\", () => A.NativeUint8List_NativeUint8List(4096));\n" " _lazyFinal(\$, \"_Utf8Decoder__decoder\", \"\$get\$_Utf8Decoder__decoder\", () => new A._Utf8Decoder__decoder_closure().call\$0());\n" " _lazyFinal(\$, \"_Utf8Decoder__decoderNonfatal\", \"\$get\$_Utf8Decoder__decoderNonfatal\", () => new A._Utf8Decoder__decoderNonfatal_closure().call\$0());\n" @@ -22906,11 +22486,8 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " Function.prototype.call\$0 = function() {\n" " return this();\n" " };\n" -" Function.prototype.call\$1\$1 = function(a) {\n" -" return this(a);\n" -" };\n" -" Function.prototype.call\$3\$3 = function(a, b, c) {\n" -" return this(a, b, c);\n" +" Function.prototype.call\$1\$4 = function(a, b, c, d) {\n" +" return this(a, b, c, d);\n" " };\n" " Function.prototype.call\$5 = function(a, b, c, d, e) {\n" " return this(a, b, c, d, e);\n" @@ -22924,33 +22501,18 @@ const injectedClientJs = "// Generated by dart2js (, csp, intern-composite-value " Function.prototype.call\$3\$6 = function(a, b, c, d, e, f) {\n" " return this(a, b, c, d, e, f);\n" " };\n" -" Function.prototype.call\$1\$4 = function(a, b, c, d) {\n" +" Function.prototype.call\$3\$4 = function(a, b, c, d) {\n" " return this(a, b, c, d);\n" " };\n" -" Function.prototype.call\$2\$1 = function(a) {\n" -" return this(a);\n" -" };\n" " Function.prototype.call\$2\$5 = function(a, b, c, d, e) {\n" " return this(a, b, c, d, e);\n" " };\n" " Function.prototype.call\$2\$4 = function(a, b, c, d) {\n" " return this(a, b, c, d);\n" " };\n" -" Function.prototype.call\$3\$1 = function(a) {\n" +" Function.prototype.call\$1\$1 = function(a) {\n" " return this(a);\n" " };\n" -" Function.prototype.call\$3\$4 = function(a, b, c, d) {\n" -" return this(a, b, c, d);\n" -" };\n" -" Function.prototype.call\$2\$2 = function(a, b) {\n" -" return this(a, b);\n" -" };\n" -" Function.prototype.call\$2\$3 = function(a, b, c) {\n" -" return this(a, b, c);\n" -" };\n" -" Function.prototype.call\$1\$2 = function(a, b) {\n" -" return this(a, b);\n" -" };\n" " Function.prototype.call\$2\$0 = function() {\n" " return this();\n" " };\n" diff --git a/dwds/lib/src/version.dart b/dwds/lib/src/version.dart index 7a70c983c3..e5c03848be 100644 --- a/dwds/lib/src/version.dart +++ b/dwds/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '27.1.2'; +const packageVersion = '27.1.3-wip'; diff --git a/dwds/mono_pkg.yaml b/dwds/mono_pkg.yaml index cf4a65ad7e..75e57b5d12 100644 --- a/dwds/mono_pkg.yaml +++ b/dwds/mono_pkg.yaml @@ -12,6 +12,7 @@ stages: # run first for Linux. - group: - command: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + - command: echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV - test: --tags=extension sdk: dev os: @@ -22,32 +23,54 @@ stages: sdk: dev os: - windows - # First test shard: + # First test shard (Linux): - group: + - command: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + - command: echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV - test: --total-shards 3 --shard-index 0 --exclude-tags=extension sdk: dev os: - linux + # First test shard (Windows): + - group: + - test: --total-shards 3 --shard-index 0 --exclude-tags=extension + sdk: dev + os: - windows - # Second test shard: + # Second test shard (Linux): - group: + - command: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + - command: echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV - test: --total-shards 3 --shard-index 1 --exclude-tags=extension sdk: dev os: - linux + # Second test shard (Windows): + - group: + - test: --total-shards 3 --shard-index 1 --exclude-tags=extension + sdk: dev + os: - windows - # Third test shard: + # Third test shard (Linux): - group: + - command: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + - command: echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV - test: --total-shards 3 --shard-index 2 --exclude-tags=extension sdk: dev os: - linux + # Third test shard (Windows): + - group: + - test: --total-shards 3 --shard-index 2 --exclude-tags=extension + sdk: dev + os: - windows - beta_cron: - analyze: . sdk: beta - group: - command: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + - command: echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV - test: -j 1 sdk: beta - test: -j 1 diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml index 42a1b307cb..9089b186e5 100644 --- a/dwds/pubspec.yaml +++ b/dwds/pubspec.yaml @@ -1,6 +1,6 @@ name: dwds # Every time this changes you need to run `dart run tool/build.dart`. -version: 27.1.2 +version: 27.1.3-wip description: >- A service that proxies between the Chrome debug protocol and the Dart VM diff --git a/dwds/test/integration/circular_evaluate_ddc_library_bundle_test.dart b/dwds/test/integration/circular_evaluate_ddc_library_bundle_test.dart deleted file mode 100644 index a45d9fcfe8..0000000000 --- a/dwds/test/integration/circular_evaluate_ddc_library_bundle_test.dart +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2026, 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. - -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 5)) -library; - -import 'dart:io'; - -import 'package:dwds/expression_compiler.dart'; -import 'package:dwds_test_common/test_sdk_configuration.dart'; -import 'package:test/test.dart'; - -import 'evaluate_circular_common.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; - -void main() async { - // Enable verbose logging for debugging. - const debug = false; - - final provider = TestSdkConfigurationProvider( - verbose: debug, - ddcModuleFormat: ModuleFormat.ddc, - canaryFeatures: true, - ); - tearDownAll(provider.dispose); - - group('Build Daemon |', () { - testAll(provider: provider, compilationMode: CompilationMode.buildDaemon); - }); - - group('Frontend Server |', () { - group('Context with circular dependencies |', () { - for (final indexBaseMode in IndexBaseMode.values) { - group( - 'with ${indexBaseMode.name} |', - () { - testAll( - provider: provider, - compilationMode: CompilationMode.frontendServer, - indexBaseMode: indexBaseMode, - useDebuggerModuleNames: true, - ); - }, - skip: - // https://github.com/dart-lang/sdk/issues/49277 - indexBaseMode == IndexBaseMode.base && Platform.isWindows, - ); - } - }); - }); -} diff --git a/dwds/test/integration/dart_uri_file_uri_test.dart b/dwds/test/integration/dart_uri_file_uri_test.dart deleted file mode 100644 index c06a40cc7d..0000000000 --- a/dwds/test/integration/dart_uri_file_uri_test.dart +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2019, 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') -@Timeout(Duration(minutes: 2)) -library; - -import 'package:dwds/src/utilities/dart_uri.dart'; -import 'package:dwds_test_common/test_sdk_configuration.dart'; -import 'package:path/path.dart' as p; -import 'package:test/test.dart'; - -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - -// This tests converting file Uris into our internal paths. -// -// These tests are separated out because we need a running isolate in order to -// look up packages. -void main() { - final provider = TestSdkConfigurationProvider(); - tearDownAll(provider.dispose); - - final testProject = TestProject.test; - final testPackageProject = TestProject.testPackage(); - - final context = TestContext(testPackageProject, provider); - - for (final compilationMode in CompilationMode.values.where( - (mode) => !mode.usesDdcModulesOnly, - )) { - group('$compilationMode |', () { - for (final useDebuggerModuleNames in [false, true]) { - group('Debugger module names: $useDebuggerModuleNames |', () { - final appServerPath = compilationMode.usesFrontendServer - ? 'web/main.dart' - : 'main.dart'; - - final serverPath = - compilationMode.usesFrontendServer && useDebuggerModuleNames - ? 'packages/${testPackageProject.packageDirectory}/lib/test_library.dart' - : 'packages/${testPackageProject.packageName}/test_library.dart'; - - final anotherServerPath = - compilationMode.usesFrontendServer && useDebuggerModuleNames - ? 'packages/${testProject.packageDirectory}/lib/library.dart' - : 'packages/${testProject.packageName}/library.dart'; - - setUpAll(() async { - await context.setUp( - testSettings: TestSettings( - compilationMode: compilationMode, - useDebuggerModuleNames: useDebuggerModuleNames, - ), - ); - }); - - tearDownAll(() async { - await context.tearDown(); - }); - - test('file path to org-dartlang-app', () { - final webMain = Uri.file( - p.join( - // The directory for the _testPackage package which imports - // _test. - testPackageProject.absolutePackageDirectory, - 'web', - 'main.dart', - ), - ); - final uri = DartUri('$webMain'); - expect(uri.serverPath, appServerPath); - }); - - test('file path to this package', () { - final testPackageLib = Uri.file( - p.join( - testPackageProject.absolutePackageDirectory, - 'lib', - 'test_library.dart', - ), - ); - final uri = DartUri('$testPackageLib'); - expect(uri.serverPath, serverPath); - }); - - test('file path to another package', () { - final testLib = Uri.file( - p.join( - // The directory for the general _test package. This is going to - // be relative to the project in the `TestContext`. - testPackageProject.absolutePackageDirectory, - '..', - testProject.packageDirectory, - 'lib', - 'library.dart', - ), - ); - final dartUri = DartUri('$testLib'); - expect(dartUri.serverPath, anotherServerPath); - }); - }); - } - }); - } -} diff --git a/dwds/test/integration/dart_uri_test.dart b/dwds/test/integration/dart_uri_test.dart index 9a0d5babdc..d436181ea2 100644 --- a/dwds/test/integration/dart_uri_test.dart +++ b/dwds/test/integration/dart_uri_test.dart @@ -7,13 +7,12 @@ library; import 'package:dwds/src/utilities/dart_uri.dart'; +import 'package:dwds_test_common/fixtures/fakes.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; -import 'fixtures/fakes.dart'; -import 'fixtures/utilities.dart'; - class TestStrategy extends FakeStrategy { TestStrategy(super.assetReader); diff --git a/dwds/test/integration/debugger_test.dart b/dwds/test/integration/debugger_test.dart index 5786af38ea..83a9c25d95 100644 --- a/dwds/test/integration/debugger_test.dart +++ b/dwds/test/integration/debugger_test.dart @@ -12,16 +12,15 @@ import 'package:dwds/src/debugging/debugger.dart'; import 'package:dwds/src/debugging/frame_computer.dart'; import 'package:dwds/src/debugging/location.dart'; import 'package:dwds/src/debugging/skip_list.dart'; +import 'package:dwds_test_common/fixtures/debugger_data.dart'; +import 'package:dwds_test_common/fixtures/fakes.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:logging/logging.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart' hide LogRecord; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart' show CallFrame, DebuggerPausedEvent, StackTrace, WipCallFrame, WipScript; -import 'fixtures/debugger_data.dart'; -import 'fixtures/fakes.dart'; -import 'fixtures/utilities.dart'; - late FakeChromeAppInspector inspector; late Debugger debugger; late FakeWebkitDebugger webkitDebugger; diff --git a/dwds/test/integration/evaluate_ddc_library_bundle_test.dart b/dwds/test/integration/evaluate_ddc_library_bundle_test.dart deleted file mode 100644 index e8783c8c8d..0000000000 --- a/dwds/test/integration/evaluate_ddc_library_bundle_test.dart +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2026, 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. - -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 5)) -library; - -import 'dart:io'; - -import 'package:dwds/expression_compiler.dart'; -import 'package:dwds_test_common/test_sdk_configuration.dart'; -import 'package:test/test.dart'; - -import 'evaluate_common.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; - -void main() async { - // Enable verbose logging for debugging. - const debug = false; - - group('Canary: true |', () { - final provider = TestSdkConfigurationProvider( - verbose: debug, - ddcModuleFormat: ModuleFormat.ddc, - canaryFeatures: true, - ); - tearDownAll(provider.dispose); - - group('Build Daemon |', () { - testAll(provider: provider, compilationMode: CompilationMode.buildDaemon); - }); - - group('Frontend Server |', () { - for (final useDebuggerModuleNames in [false, true]) { - group('Debugger module names: $useDebuggerModuleNames |', () { - for (final indexBaseMode in IndexBaseMode.values) { - group( - 'with ${indexBaseMode.name} |', - () { - testAll( - provider: provider, - compilationMode: CompilationMode.frontendServer, - indexBaseMode: indexBaseMode, - useDebuggerModuleNames: useDebuggerModuleNames, - ); - }, - // https://github.com/dart-lang/sdk/issues/49277 - skip: indexBaseMode == IndexBaseMode.base && Platform.isWindows - ? 'Skipped on Windows when indexBaseMode is base. See issue: https://github.com/dart-lang/sdk/issues/49277' - : null, - ); - } - }); - } - }); - }); -} diff --git a/dwds/test/integration/execution_context_test.dart b/dwds/test/integration/execution_context_test.dart index 5ec431aa0a..d382f389b9 100644 --- a/dwds/test/integration/execution_context_test.dart +++ b/dwds/test/integration/execution_context_test.dart @@ -12,12 +12,11 @@ import 'package:dwds/data/devtools_request.dart'; import 'package:dwds/data/extension_request.dart'; import 'package:dwds/src/debugging/execution_context.dart'; import 'package:dwds/src/servers/extension_debugger.dart'; +import 'package:dwds_test_common/fixtures/fakes.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:test/test.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; -import 'fixtures/fakes.dart'; - void main() async { const debug = false; diff --git a/dwds/test/integration/expression_compiler_service_ddc_library_bundle_test.dart b/dwds/test/integration/expression_compiler_service_ddc_library_bundle_test.dart index 53ce3674a1..cd1a7fe63a 100644 --- a/dwds/test/integration/expression_compiler_service_ddc_library_bundle_test.dart +++ b/dwds/test/integration/expression_compiler_service_ddc_library_bundle_test.dart @@ -2,15 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; -import 'package:test/test.dart'; - -import 'expression_compiler_service_common.dart'; +import 'package:dwds_test_common/integration/expression_compiler_service.dart'; void main() async { testAll( diff --git a/dwds/test/integration/expression_evaluator_test.dart b/dwds/test/integration/expression_evaluator_test.dart index 92a0be7316..72c4445634 100644 --- a/dwds/test/integration/expression_evaluator_test.dart +++ b/dwds/test/integration/expression_evaluator_test.dart @@ -14,15 +14,13 @@ import 'package:dwds/src/debugging/skip_list.dart'; import 'package:dwds/src/services/batched_expression_evaluator.dart'; import 'package:dwds/src/services/expression_evaluator.dart'; import 'package:dwds/src/utilities/shared.dart'; - +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/fakes.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart' hide LogRecord; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; -import 'fixtures/context.dart'; -import 'fixtures/fakes.dart'; -import 'fixtures/utilities.dart'; - late ExpressionEvaluator? _evaluator; late ExpressionEvaluator? _batchedEvaluator; diff --git a/dwds/test/integration/extension_debugger_test.dart b/dwds/test/integration/extension_debugger_test.dart index 024ead4849..907be2f60a 100644 --- a/dwds/test/integration/extension_debugger_test.dart +++ b/dwds/test/integration/extension_debugger_test.dart @@ -11,12 +11,11 @@ import 'dart:convert'; import 'package:dwds/data/devtools_request.dart'; import 'package:dwds/data/extension_request.dart'; import 'package:dwds/src/servers/extension_debugger.dart'; +import 'package:dwds_test_common/fixtures/debugger_data.dart'; +import 'package:dwds_test_common/fixtures/fakes.dart'; import 'package:test/test.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; -import 'fixtures/debugger_data.dart'; -import 'fixtures/fakes.dart'; - late FakeSseConnection connection; late ExtensionDebugger extensionDebugger; diff --git a/dwds/test/integration/fixtures/context.dart b/dwds/test/integration/fixtures/context.dart deleted file mode 100644 index 632e7bd798..0000000000 --- a/dwds/test/integration/fixtures/context.dart +++ /dev/null @@ -1,957 +0,0 @@ -// Copyright (c) 2019, 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. - -// @skip_package_deps_validation - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:build_daemon/client.dart'; -import 'package:build_daemon/data/build_status.dart'; -import 'package:build_daemon/data/build_target.dart'; -import 'package:dwds/asset_reader.dart'; -import 'package:dwds/dart_web_debug_service.dart'; -import 'package:dwds/src/connections/app_connection.dart'; -import 'package:dwds/src/connections/debug_connection.dart'; -import 'package:dwds/src/debugging/webkit_debugger.dart'; -import 'package:dwds/src/loaders/build_runner_strategy_provider.dart'; -import 'package:dwds/src/loaders/frontend_server_strategy_provider.dart'; -import 'package:dwds/src/loaders/strategy.dart'; -import 'package:dwds/src/readers/proxy_server_asset_reader.dart'; -import 'package:dwds/src/services/chrome/chrome_proxy_service.dart'; -import 'package:dwds/src/services/expression_compiler.dart'; -import 'package:dwds/src/services/expression_compiler_service.dart'; -import 'package:dwds/src/utilities/dart_uri.dart'; -import 'package:dwds/src/utilities/server.dart'; -import 'package:dwds_test_common/logging.dart'; -import 'package:dwds_test_common/test_sdk_configuration.dart'; -import 'package:dwds_test_common/utilities.dart'; -import 'package:file/local.dart'; -import 'package:http/http.dart'; -import 'package:http/io_client.dart'; -import 'package:logging/logging.dart' as logging; -import 'package:path/path.dart' as p; -import 'package:shelf/shelf.dart' as shelf; -import 'package:shelf/shelf.dart'; -import 'package:shelf_proxy/shelf_proxy.dart'; -import 'package:test/test.dart'; -import 'package:vm_service/vm_service.dart'; -import 'package:vm_service/vm_service_io.dart'; -import 'package:webdriver/async_io.dart'; -import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; - -import '../../frontend_server_common/devfs.dart'; -import '../../frontend_server_common/resident_runner.dart'; -import 'project.dart'; -import 'server.dart'; -import 'utilities.dart'; - -final _exeExt = Platform.isWindows ? '.exe' : ''; - -const isRPCError = TypeMatcher(); -const isSentinelException = TypeMatcher(); - -final Matcher throwsRPCError = throwsA(isRPCError); -final Matcher throwsSentinelException = throwsA(isSentinelException); - -Matcher isRPCErrorWithMessage(String message) => isA().having( - (RPCError e) => e.message, - 'message', - contains(message), -); -Matcher throwsRPCErrorWithMessage(String message) => - throwsA(isRPCErrorWithMessage(message)); - -Matcher isRPCErrorWithCode(int code) => - isA().having((RPCError e) => e.code, 'code', equals(code)); -Matcher throwsRPCErrorWithCode(int code) => throwsA(isRPCErrorWithCode(code)); - -enum CompilationMode { - buildDaemon(false, true, false), - frontendServer(true, false, false), - buildDaemonAndFrontendServer(true, true, true); - - final bool usesFrontendServer; - final bool usesBuildDaemon; - final bool usesDdcModulesOnly; - - const CompilationMode( - this.usesFrontendServer, - this.usesBuildDaemon, - this.usesDdcModulesOnly, - ); -} - -class TestContext { - final TestProject project; - final TestSdkConfigurationProvider sdkConfigurationProvider; - - String get appUrl => _appUrl!; - late String? _appUrl; - - WipConnection get tabConnection => _tabConnection!; - late WipConnection? _tabConnection; - - TestServer get testServer => _testServer!; - TestServer? _testServer; - - Dwds? get dwds => _testServer?.dwds; - - BuildDaemonClient get daemonClient => _daemonClient!; - BuildDaemonClient? _daemonClient; - - ResidentWebRunner get webRunner => _webRunner!; - ResidentWebRunner? _webRunner; - - WebDriver get webDriver => _webDriver!; - WebDriver? _webDriver; - - Process get chromeDriver => _chromeDriver!; - Process? _chromeDriver; - - WebkitDebugger get webkitDebugger => _webkitDebugger!; - late WebkitDebugger? _webkitDebugger; - - Handler get assetHandler => _assetHandler!; - late Handler? _assetHandler; - - Client get client => _client!; - Client? _client; - - ExpressionCompilerService? ddcService; - - int get port => _port!; - late int? _port; - - Directory get outputDir => _outputDir!; - Directory? _outputDir; - - late WipConnection extensionConnection; - late AppConnection appConnection; - late DebugConnection debugConnection; - - final _logger = logging.Logger('Context'); - - final _serviceNameToMethod = {}; - - late LocalFileSystem frontendServerFileSystem; - - late String _hostname; - - /// Internal VM service. - /// - /// Prefer using [vmService] instead in tests when possible, to include - /// testing of the VmServerConnection (bypassed when using [service]). - ChromeProxyService get service => fetchChromeProxyService(debugConnection); - - /// External VM service. - VmService get vmService => debugConnection.vmService; - - TestContext(this.project, this.sdkConfigurationProvider); - - Future setUp({ - TestSettings testSettings = const TestSettings(), - TestAppMetadata appMetadata = const TestAppMetadata.externalApp(), - TestDebugSettings debugSettings = - const TestDebugSettings.noDevToolsLaunch(), - }) async { - try { - // Build settings to return from load strategy. - final buildSettings = TestBuildSettings( - appEntrypoint: project.dartEntryFilePackageUri, - canaryFeatures: testSettings.canaryFeatures, - isFlutterApp: testSettings.isFlutterApp, - experiments: testSettings.experiments, - ); - - // Make sure configuration was created correctly. - final sdkLayout = sdkConfigurationProvider.sdkLayout; - final configuration = await sdkConfigurationProvider.configuration; - configuration.validate(); - await project.setUp(); - - DartUri.currentDirectory = project.absolutePackageDirectory; - - _logger.info( - 'Serving: ${project.directoryToServe}/${project.filePathToServe}', - ); - _logger.info('Project: ${project.absolutePackageDirectory}'); - _logger.info('Packages: ${project.packageConfigFile}'); - _logger.info('Entry: ${project.dartEntryFilePath}'); - - configureLogWriter(); - - _client = IOClient( - HttpClient() - ..maxConnectionsPerHost = 200 - ..idleTimeout = const Duration(seconds: 30) - ..connectionTimeout = const Duration(seconds: 30), - ); - - final systemTempDir = Directory.systemTemp; - _outputDir = systemTempDir.createTempSync('foo bar'); - - final chromeDriverPort = await findUnusedPort(); - final chromeDriverUrlBase = 'wd/hub'; - try { - _chromeDriver = await Process.start('chromedriver$_exeExt', [ - '--port=$chromeDriverPort', - '--url-base=$chromeDriverUrlBase', - ]); - final stdOutLines = chromeDriver.stdout - .transform(utf8.decoder) - .transform(const LineSplitter()) - .asBroadcastStream(); - - final stdErrLines = chromeDriver.stderr - .transform(utf8.decoder) - .transform(const LineSplitter()) - .asBroadcastStream(); - - // Sometimes ChromeDriver can be slow to startup. - // This was seen on a github actions run: - // > 11:22:59.924700: ChromeDriver stdout: Starting ChromeDriver - // > 139.0.7258.154 ([...]) on port 38107 - // > [...] - // > 11:23:00.237350: ChromeDriver stdout: ChromeDriver was started - // > successfully on port 38107. - // Where in the 300+ ms it took before it was actually ready to accept - // a connection we had tried - and failed - to connect. - // We therefore wait until ChromeDriver reports that it has started - // successfully. - - final chromeDriverStartup = Completer(); - stdOutLines.listen((line) { - if (!chromeDriverStartup.isCompleted && - line.contains('was started successfully')) { - chromeDriverStartup.complete(); - } - _logger.finest('ChromeDriver stdout: $line'); - }); - stdErrLines.listen( - (line) => _logger.warning('ChromeDriver stderr: $line'), - ); - - await chromeDriverStartup.future; - } catch (e) { - throw StateError( - 'Could not start ChromeDriver. Is it installed?\nError: $e', - ); - } - - await Process.run(sdkLayout.dartPath, [ - 'pub', - 'upgrade', - ], workingDirectory: project.absolutePackageDirectory); - - ExpressionCompiler? expressionCompiler; - AssetReader assetReader; - Stream buildResults; - LoadStrategy loadStrategy; - var basePath = ''; - var filePathToServe = project.filePathToServe; - - // Start the HTTP server and save its used port. - final httpServer = await startHttpServer('localhost'); - _port = httpServer.port; - - final reloadedSourcesUri = Uri.parse( - 'http://localhost:$_port/${WebDevFS.reloadedSourcesFileName}', - ); - - switch (testSettings.compilationMode) { - case CompilationMode.buildDaemon: - { - final options = [ - if (testSettings.enableExpressionEvaluation) ...[ - '--define', - 'build_web_compilers|ddc=generate-full-dill=true', - ], - for (final experiment in buildSettings.experiments) - '--enable-experiment=$experiment', - if (buildSettings.canaryFeatures) ...[ - '--define', - 'build_web_compilers|ddc=canary=true', - '--define', - 'build_web_compilers|sdk_js=canary=true', - ], - if (testSettings.moduleFormat == ModuleFormat.ddc) ...[ - '--define', - 'build_web_compilers|ddc=ddc-library-bundle=true', - '--define', - 'build_web_compilers|sdk_js=ddc-library-bundle=true', - '--define', - 'build_web_compilers|entrypoint=ddc-library-bundle=true', - '--define', - 'build_web_compilers|entrypoint_marker=ddc-library-bundle=true', - ], - '--verbose', - ]; - _daemonClient = await connectClient( - sdkLayout.dartPath, - project.absolutePackageDirectory, - options, - (log) { - final record = log.toLogRecord(); - final name = record.loggerName == '' - ? '' - : '${record.loggerName}: '; - _logger.log( - record.level, - '$name${record.message}', - record.error, - record.stackTrace, - ); - }, - ); - daemonClient.registerBuildTarget( - DefaultBuildTarget((b) => b..target = project.directoryToServe), - ); - daemonClient.startBuild(); - - await waitForSuccessfulBuild(); - - final assetServerPort = daemonPort( - project.absolutePackageDirectory, - ); - _assetHandler = _createBuildRunnerProxyHandler(assetServerPort); - if (testSettings.moduleFormat == ModuleFormat.ddc && - buildSettings.canaryFeatures) { - _assetHandler = _handleReloadedSources(_assetHandler!); - } - assetReader = ProxyServerAssetReader( - assetServerPort, - root: project.directoryToServe, - ); - - if (testSettings.enableExpressionEvaluation) { - ddcService = ExpressionCompilerService( - 'localhost', - _port!, - verbose: testSettings.verboseCompiler, - sdkConfigurationProvider: sdkConfigurationProvider, - ); - expressionCompiler = ddcService; - } - - loadStrategy = switch (( - testSettings.moduleFormat, - buildSettings.canaryFeatures, - )) { - (ModuleFormat.ddc, true) => - BuildRunnerDdcLibraryBundleStrategyProvider( - testSettings.reloadConfiguration, - assetReader, - buildSettings, - reloadedSourcesUri: reloadedSourcesUri, - ).strategy, - (ModuleFormat.ddc, false) => throw Exception( - 'Unsupported DDC configuration: build daemon + canary (false) ' - '+ DDC module format ${testSettings.moduleFormat.name}.', - ), - - _ => BuildRunnerRequireStrategyProvider( - testSettings.reloadConfiguration, - assetReader, - buildSettings, - ).strategy, - }; - - buildResults = daemonClient.buildResults; - } - break; - case CompilationMode.frontendServer: - { - filePathToServe = webCompatiblePath([ - project.directoryToServe, - project.filePathToServe, - ]); - - _logger.info('Serving: $filePathToServe'); - - final entry = p.toUri( - p.join(project.webAssetsPath, project.dartEntryFileName), - ); - frontendServerFileSystem = const LocalFileSystem(); - final packageUriMapper = await PackageUriMapper.create( - frontendServerFileSystem, - project.packageConfigFile, - useDebuggerModuleNames: testSettings.useDebuggerModuleNames, - ); - - final compilerOptions = TestCompilerOptions( - experiments: buildSettings.experiments, - canaryFeatures: buildSettings.canaryFeatures, - moduleFormat: testSettings.moduleFormat, - ); - - _webRunner = ResidentWebRunner( - mainUri: entry, - urlTunneler: debugSettings.urlEncoder, - projectDirectory: Directory(project.absolutePackageDirectory).uri, - packageConfigFile: project.packageConfigFile, - packageUriMapper: packageUriMapper, - fileSystemRoots: [ - Directory(project.absolutePackageDirectory).uri, - ], - fileSystemScheme: 'org-dartlang-app', - outputPath: outputDir.path, - compilerOptions: compilerOptions, - sdkLayout: sdkLayout, - verbose: testSettings.verboseCompiler, - ); - - final assetServerPort = await findUnusedPort(); - _hostname = appMetadata.hostname; - await webRunner.run( - frontendServerFileSystem, - hostname: _hostname, - port: assetServerPort, - index: filePathToServe, - ); - - if (testSettings.enableExpressionEvaluation) { - expressionCompiler = webRunner.expressionCompiler; - } - - basePath = webRunner.devFS!.assetServer.basePath; - assetReader = webRunner.devFS!.assetServer; - _assetHandler = webRunner.devFS!.assetServer.handleRequest; - loadStrategy = switch (testSettings.moduleFormat) { - ModuleFormat.amd => FrontendServerRequireStrategyProvider( - testSettings.reloadConfiguration, - assetReader, - packageUriMapper, - () async => {}, - buildSettings, - ).strategy, - ModuleFormat.ddc => - buildSettings.canaryFeatures - ? FrontendServerDdcLibraryBundleStrategyProvider( - testSettings.reloadConfiguration, - assetReader, - packageUriMapper, - () async => {}, - buildSettings, - reloadedSourcesUri: reloadedSourcesUri, - ).strategy - : FrontendServerDdcStrategyProvider( - testSettings.reloadConfiguration, - assetReader, - packageUriMapper, - () async => {}, - buildSettings, - ).strategy, - _ => throw Exception( - 'Unsupported DDC module format ' - '${testSettings.moduleFormat.name}.', - ), - }; - buildResults = const Stream.empty(); - } - break; - case CompilationMode.buildDaemonAndFrontendServer: - { - final options = [ - if (testSettings.enableExpressionEvaluation) ...[ - '--define', - 'build_web_compilers|ddc=generate-full-dill=true', - ], - for (final experiment in buildSettings.experiments) - '--enable-experiment=$experiment', - '--define', - 'build_web_compilers|ddc=canary=true', - '--define', - 'build_web_compilers|sdk_js=canary=true', - '--define', - 'build_web_compilers|sdk_js=web-hot-reload=true', - '--define', - 'build_web_compilers|entrypoint=web-hot-reload=true', - '--define', - 'build_web_compilers|entrypoint_marker=web-hot-reload=true', - '--define', - 'build_web_compilers|entrypoint_marker=web-assets-path=' - '${project.webAssetsPath}', - '--define', - 'build_web_compilers|ddc=web-hot-reload=true', - '--define', - 'build_web_compilers|ddc_modules=web-hot-reload=true', - '--verbose', - ]; - _daemonClient = await connectClient( - sdkLayout.dartPath, - project.absolutePackageDirectory, - options, - (log) { - final record = log.toLogRecord(); - final name = record.loggerName == '' - ? '' - : '${record.loggerName}: '; - _logger.log( - record.level, - '$name${record.message}', - record.error, - record.stackTrace, - ); - }, - ); - daemonClient.registerBuildTarget( - DefaultBuildTarget((b) => b..target = project.directoryToServe), - ); - daemonClient.startBuild(); - - await waitForSuccessfulBuild(); - - final assetServerPort = daemonPort( - project.absolutePackageDirectory, - ); - _assetHandler = _createBuildRunnerProxyHandler(assetServerPort); - if (testSettings.moduleFormat == ModuleFormat.ddc && - buildSettings.canaryFeatures) { - _assetHandler = _handleReloadedSources(_assetHandler!); - } - assetReader = ProxyServerAssetReader( - assetServerPort, - root: project.directoryToServe, - ); - - if (testSettings.enableExpressionEvaluation) { - ddcService = ExpressionCompilerService( - 'localhost', - _port!, - verbose: testSettings.verboseCompiler, - sdkConfigurationProvider: sdkConfigurationProvider, - ); - expressionCompiler = ddcService; - } - frontendServerFileSystem = const LocalFileSystem(); - final packageUriMapper = await PackageUriMapper.create( - frontendServerFileSystem, - project.packageConfigFile, - useDebuggerModuleNames: testSettings.useDebuggerModuleNames, - ); - loadStrategy = switch (( - testSettings.moduleFormat, - buildSettings.canaryFeatures, - )) { - (ModuleFormat.ddc, true) => - FrontendServerDdcLibraryBundleStrategyProvider( - testSettings.reloadConfiguration, - assetReader, - packageUriMapper, - () async => {}, - buildSettings, - injectScriptLoad: false, - reloadedSourcesUri: reloadedSourcesUri, - ).strategy, - _ => throw Exception( - 'Unsupported DDC module format when compiling with Frontend ' - 'Server + build_runner ${testSettings.moduleFormat.name}.', - ), - }; - buildResults = const Stream.empty(); - } - break; - } - - final debugPort = await findUnusedPort(); - if (testSettings.launchChrome) { - // If the environment variable DWDS_DEBUG_CHROME is set to the string - // true then Chrome will be launched with a UI rather than headless. - // If the extension is enabled, then Chrome will be launched with a UI - // since headless Chrome does not support extensions. - final enableDebugExtension = debugSettings.enableDebugExtension; - final headless = - Platform.environment['DWDS_DEBUG_CHROME'] != 'true' && - !enableDebugExtension; - if (enableDebugExtension) { - await _buildDebugExtension(); - } - final capabilities = Capabilities.chrome - ..addAll({ - Capabilities.chromeOptions: { - 'args': [ - // --disable-gpu speeds up the tests that use ChromeDriver when - // they are run on GitHub Actions. - '--disable-gpu', - 'remote-debugging-port=$debugPort', - if (enableDebugExtension) - '--load-extension=debug_extension/prod_build', - if (headless) '--headless', - ], - }, - }); - _webDriver = await createDriver( - spec: WebDriverSpec.JsonWire, - desired: capabilities, - uri: Uri.parse( - 'http://127.0.0.1:$chromeDriverPort/$chromeDriverUrlBase/', - ), - ); - } - - // The debugger tab must be enabled and connected before certain - // listeners in DWDS or `main` is run. - final tabConnectionCompleter = Completer(); - final appConnectionCompleter = Completer(); - final connection = ChromeConnection('localhost', debugPort); - - // TODO(srujzs): In the case of the frontend server, it doesn't make sense - // that we initialize a new HTTP server instead of reusing the one in - // `TestAssetServer`. We should instead use that one to align with Flutter - // tools. - _testServer = await TestServer.start( - debugSettings: debugSettings.copyWith( - expressionCompiler: expressionCompiler, - ), - appMetadata: appMetadata, - port: port, - assetHandler: assetHandler, - assetReader: assetReader, - strategy: loadStrategy, - target: project.directoryToServe, - buildResults: buildResults, - chromeConnection: () async => connection, - httpServer: httpServer, - ); - - _testServer!.dwds.connectedApps.listen((connection) async { - // Ensure that we've established a tab connection before running main. - await tabConnectionCompleter.future; - if (testSettings.autoRun) { - connection.runMain(); - } - - // We may reuse the app connection, so only save it the first time - // it's encountered. - if (!appConnectionCompleter.isCompleted) { - appConnection = connection; - appConnectionCompleter.complete(); - } - }); - - _appUrl = basePath.isEmpty - ? 'http://localhost:$port/$filePathToServe' - : 'http://localhost:$port/$basePath/$filePathToServe'; - - if (testSettings.launchChrome) { - await _webDriver?.get(appUrl); - _tabConnection = await _getTabConnection(connection, appUrl); - tabConnectionCompleter.complete(); - - if (debugSettings.enableDebugExtension) { - final extensionTab = await _fetchDartDebugExtensionTab(connection); - extensionConnection = await extensionTab.connect(); - await extensionConnection.runtime.enable(); - } - - await appConnectionCompleter.future; - if (debugSettings.enableDebugging && !testSettings.waitToDebug) { - await startDebugging(); - } - _webkitDebugger = WebkitDebugger(WipDebugger(tabConnection)); - } else { - // No tab needs to be discovered, so fulfill the relevant completer. - tabConnectionCompleter.complete(); - } - } catch (e, s) { - _logger.severe('Failed to setup the service, $e:$s'); - await tearDown(); - rethrow; - } - } - - /// Creates a VM service connection connected to the debug URI. - /// - /// This can be used to test behavior that should be available to a client - /// connected to DWDS. - Future connectFakeClient() async { - final fakeClient = await vmServiceConnectUri(debugConnection.uri); - - fakeClient.onEvent(EventStreams.kService).listen(_handleServiceEvent); - await fakeClient.streamListen(EventStreams.kService); - - return fakeClient; - } - - /// Returns the service extension method given the [extensionName]. - /// - /// The extension be called by a client created with [connectFakeClient]. - String? getRegisteredServiceExtension(String extensionName) { - if (_serviceNameToMethod.isEmpty) { - throw StateError(''' - No registered service extensions. Did you call connectFakeClient? - '''); - } - - return _serviceNameToMethod[extensionName]; - } - - void _handleServiceEvent(Event e) { - if (e.kind == EventKind.kServiceRegistered) { - final serviceName = e.service!; - _serviceNameToMethod[serviceName] = e.method; - } - } - - Future startDebugging() async { - debugConnection = await testServer.dwds.debugConnection(appConnection); - } - - Future tearDown() async { - await _webRunner?.stop(); - await _webDriver?.quit(closeSession: true); - _chromeDriver?.kill(); - DartUri.currentDirectory = p.current; - await _daemonClient?.close(); - await ddcService?.stop(); - await _testServer?.stop(); - _client?.close(); - await _outputDir?.delete(recursive: true); - stopLogWriter(); - await project.tearDown(); - - // clear the state for next setup - _webDriver = null; - _chromeDriver = null; - _daemonClient = null; - ddcService = null; - _webRunner = null; - _testServer = null; - _client = null; - _outputDir = null; - } - - /// Given a list of edits, use file IO to write them to the file system. - /// - /// If `file` has the same name as the project's entry file name, that file - /// will be edited. Otherwise, it's assumed to be a library file. - // TODO(srujzs): It's possible we may want a library file with the same name - // as the entry file, but this function doesn't allow that. Potentially - // support that. - Future makeEdits(List edits) async { - // `dart:io`'s `stat` on Windows does not have millisecond precision so we - // need to make sure we wait long enough that modifications result in a - // timestamp that is guaranteed to be after the previous compile. - // TODO(https://github.com/dart-lang/sdk/issues/51937): Remove once this bug - // is fixed. - if (Platform.isWindows) { - await Future.delayed(const Duration(seconds: 1)); - } - _reloadedSources.clear(); - for (var (:file, :originalString, :newString) in edits) { - if (file == project.dartEntryFileName) { - file = project.dartEntryFilePath; - } else { - file = project.dartLibFilePath(file); - } - final f = File(file); - final fileContents = f.readAsStringSync(); - f.writeAsStringSync(fileContents.replaceAll(originalString, newString)); - - _updateReloadedSources(file); - } - } - - /// Updates the reloaded_sources.json manifest file for a running test. - /// - /// This logic essentially replicates the build system's naming conventions - /// for DDC's generated code. DWDS itself uses the metadata file, but this - /// isn't available for our test fixtures. - /// Rules: - /// - Entrypoints (served): web/main.dart -> main - /// - Entrypoints (nested): test/hello_world/main.dart -> hello_world/main - /// - Library files: lib/path/to/some_file.dart - /// -> packages/`package`/path/to/some_file - void _updateReloadedSources(String absolutePath) { - final relativePath = p.relative( - absolutePath, - from: project.absolutePackageDirectory, - ); - final relativeUrl = p.toUri(relativePath).path; - - String moduleName; - String libUri; - String srcPath; - - if (relativeUrl.startsWith('lib/')) { - final pathInLib = relativeUrl.substring(4); - moduleName = - 'packages/${project.packageName}/${p.withoutExtension(pathInLib)}'; - libUri = 'package:${project.packageName}/$pathInLib'; - srcPath = moduleName; - } else if (absolutePath == project.dartEntryFilePath) { - moduleName = p.withoutExtension(relativeUrl); - libUri = project.dartEntryFilePackageUri.toString(); - - final servePath = '${project.directoryToServe}/'; - if (relativeUrl.startsWith(servePath)) { - // e.g. web/main.dart -> main - srcPath = p.withoutExtension(relativeUrl.substring(servePath.length)); - } else { - // e.g. example/hello_world/main.dart -> example/hello_world/main - srcPath = moduleName; - } - } else { - throw StateError( - "Unhandled file path in test context's reloaded_sources.json: " - " $absolutePath. Only entrypoints and files in 'lib/' are supported.", - ); - } - - _reloadedSources.add( - WebDevFS.createReloadedSourceEntry( - src: '/$srcPath.ddc.js', - module: moduleName, - libraries: [libUri], - ), - ); - } - - /// Contains contents of the reloaded_sources.json manifest file. - /// - /// Used by the DDC Library Bundle module system to record changed files for - /// hot restart/reload. - final _reloadedSources = >[]; - - void addLibraryFile({required String libFileName, required String contents}) { - final file = File(project.dartLibFilePath(libFileName)); - // Library folder may not exist yet, so create it. - file.createSync(recursive: true); - file.writeAsStringSync(contents); - _updateReloadedSources(file.path); - } - - Handler _createBuildRunnerProxyHandler(int assetServerPort) { - return proxyHandler( - 'http://localhost:$assetServerPort/${project.directoryToServe}/', - client: client, - ); - } - - /// Wraps a handler to serve the reloaded_sources.json file for - /// reloads/restarts in the DDC Library Bundle module system. - Handler _handleReloadedSources(Handler proxy) { - return (request) { - final path = request.url.path; - if (path.endsWith(WebDevFS.reloadedSourcesFileName)) { - return shelf.Response.ok(jsonEncode(_reloadedSources)); - } - return proxy(request); - }; - } - - Future recompile({required bool fullRestart}) async { - await webRunner.rerun( - fullRestart: fullRestart, - fileServerUri: Uri.parse('http://${testServer.host}:${testServer.port}'), - ); - return; - } - - Future waitForSuccessfulBuild({ - Duration? timeout, - bool propagateToBrowser = false, - }) async { - // Wait for the build until the timeout is reached: - await daemonClient.buildResults - .firstWhere( - (BuildResults results) => results.results.any( - (BuildResult result) => result.status == BuildStatus.succeeded, - ), - ) - .timeout(timeout ?? const Duration(seconds: 60)); - - if (propagateToBrowser) { - // Allow change to propagate to the browser. - // Windows, or at least Travis on Windows, seems to need more time. - // TODO: Wait for an explicit finish signal instead of adding this delay. - final delay = Platform.isWindows - ? const Duration(seconds: 5) - : const Duration(seconds: 2); - await Future.delayed(delay); - } - } - - Future _buildDebugExtension() async { - final process = await Process.run('tool/build_extension.sh', [ - 'prod', - ], workingDirectory: absolutePath(pathFromDwds: 'debug_extension')); - print(process.stdout); - } - - Future _getTabConnection( - ChromeConnection connection, - String appUrl, - ) async { - final tab = await connection.getTab( - (t) => t.url == appUrl, - retryFor: const Duration(seconds: 5), - ); - if (tab == null) { - throw StateError( - 'Unable to connect to tab after retrying for 5 seconds.', - ); - } - final tabConnection = await tab.connect(); - await tabConnection.runtime.enable(); - await tabConnection.debugger.enable(); - return tabConnection; - } - - Future _fetchDartDebugExtensionTab( - ChromeConnection connection, - ) async { - const retries = 5; - for (var i = 0; i < retries; i++) { - if (i > 0) { - await Future.delayed(const Duration(milliseconds: 500)); - } - final extensionTabs = (await connection.getTabs()).where((tab) { - return tab.isChromeExtension; - }); - for (final tab in extensionTabs) { - final tabConnection = await tab.connect(); - final response = await tabConnection.runtime.evaluate( - 'window.isDartDebugExtension', - ); - if (response.value == true) { - return tab; - } - } - } - throw StateError('No extension installed.'); - } - - /// Finds the line number in [scriptRef] matching [breakpointId]. - /// - /// A breakpoint ID is found by looking for a line that ends with a comment - /// of exactly this form: `// Breakpoint: `. - /// - /// Throws if it can't find the matching line. - Future findBreakpointLine( - String breakpointId, - String isolateId, - ScriptRef scriptRef, - ) async { - final script = await debugConnection.vmService.getObject( - isolateId, - scriptRef.id!, - ) as Script; - final lines = LineSplitter.split(script.source!).toList(); - final lineNumber = lines.indexWhere( - (l) => l.endsWith('// Breakpoint: $breakpointId'), - ); - if (lineNumber == -1) { - throw StateError( - 'Unable to find breakpoint in ${scriptRef.uri} with id ' - '$breakpointId', - ); - } - return lineNumber + 1; - } -} - -typedef Edit = ({String file, String originalString, String newString}); diff --git a/dwds/test/integration/fixtures/frontend_server_context.dart b/dwds/test/integration/fixtures/frontend_server_context.dart new file mode 100644 index 0000000000..e125d95ed9 --- /dev/null +++ b/dwds/test/integration/fixtures/frontend_server_context.dart @@ -0,0 +1,180 @@ +// Copyright (c) 2026, 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:dwds/asset_reader.dart'; +import 'package:dwds/data/build_result.dart'; +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds/src/loaders/frontend_server_strategy_provider.dart'; +import 'package:dwds/src/loaders/strategy.dart'; +import 'package:dwds/src/utilities/server.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/utilities.dart'; +import 'package:file/local.dart'; +import 'package:logging/logging.dart' as logging; +import 'package:path/path.dart' as p; +import 'package:shelf/shelf.dart'; + +import '../../frontend_server_common/asset_server.dart'; +import '../../frontend_server_common/resident_runner.dart'; + +class FrontendServerTestContext extends TestContext { + ResidentWebRunner? _webRunner; + TestAssetServer? _assetReader; + LoadStrategy? _loadStrategy; + ExpressionCompiler? _expressionCompiler; + + late LocalFileSystem frontendServerFileSystem; + + final _logger = logging.Logger('FrontendServerContext'); + + FrontendServerTestContext(super.project, super.sdkConfigurationProvider) + : super.protected(); + + @override + String get appUrlPath => + webCompatiblePath([project.directoryToServe, project.filePathToServe]); + + @override + String get basePath => assetReader.basePath; + + @override + bool get usesFrontendServer => true; + + ResidentWebRunner get webRunner => _webRunner!; + + @override + TestAssetServer get assetReader => _assetReader!; + + @override + Handler get assetHandler => assetReader.handleRequest; + + @override + LoadStrategy get loadStrategy => _loadStrategy!; + + @override + ExpressionCompiler? get expressionCompiler => _expressionCompiler; + + @override + Stream get buildResults => const Stream.empty(); + + @override + Future modeSetUp( + TestSettings testSettings, + TestDebugSettings debugSettings, + TestAppMetadata appMetadata, + Uri reloadedSourcesUri, + ) async { + final sdkLayout = sdkConfigurationProvider.sdkLayout; + final buildSettings = TestBuildSettings( + appEntrypoint: project.dartEntryFilePackageUri, + canaryFeatures: testSettings.canaryFeatures, + isFlutterApp: testSettings.isFlutterApp, + experiments: testSettings.experiments, + ); + + final filePathToServe = webCompatiblePath([ + project.directoryToServe, + project.filePathToServe, + ]); + + _logger.info('Serving: $filePathToServe'); + + final entry = p.toUri( + p.join(project.webAssetsPath, project.dartEntryFileName), + ); + frontendServerFileSystem = const LocalFileSystem(); + final packageUriMapper = await PackageUriMapper.create( + frontendServerFileSystem, + project.packageConfigFile, + useDebuggerModuleNames: testSettings.useDebuggerModuleNames, + ); + + final compilerOptions = TestCompilerOptions( + experiments: buildSettings.experiments, + canaryFeatures: buildSettings.canaryFeatures, + moduleFormat: testSettings.moduleFormat, + ); + + _webRunner = ResidentWebRunner( + mainUri: entry, + urlTunneler: debugSettings.urlEncoder, + projectDirectory: Directory(project.absolutePackageDirectory).uri, + packageConfigFile: project.packageConfigFile, + packageUriMapper: packageUriMapper, + fileSystemRoots: [Directory(project.absolutePackageDirectory).uri], + fileSystemScheme: 'org-dartlang-app', + outputPath: outputDir.path, + compilerOptions: compilerOptions, + sdkLayout: sdkLayout, + verbose: testSettings.verboseCompiler, + ); + + final assetServerPort = await findUnusedPort(); + await webRunner.run( + frontendServerFileSystem, + hostname: appMetadata.hostname, + port: assetServerPort, + index: filePathToServe, + ); + + if (testSettings.enableExpressionEvaluation) { + _expressionCompiler = webRunner.expressionCompiler; + } else { + _expressionCompiler = null; + } + + _assetReader = webRunner.devFS!.assetServer; + + _loadStrategy = switch (testSettings.moduleFormat) { + ModuleFormat.amd => FrontendServerRequireStrategyProvider( + testSettings.reloadConfiguration, + assetReader, + packageUriMapper, + () async => {}, + buildSettings, + ).strategy, + ModuleFormat.ddc => + buildSettings.canaryFeatures + ? FrontendServerDdcLibraryBundleStrategyProvider( + testSettings.reloadConfiguration, + assetReader, + packageUriMapper, + () async => {}, + buildSettings, + reloadedSourcesUri: reloadedSourcesUri, + ).strategy + : FrontendServerDdcStrategyProvider( + testSettings.reloadConfiguration, + assetReader, + packageUriMapper, + () async => {}, + buildSettings, + ).strategy, + _ => throw Exception( + 'Unsupported DDC module format ${testSettings.moduleFormat.name}.', + ), + }; + } + + @override + Future modeTearDown() async { + await _webRunner?.stop(); + _webRunner = null; + _assetReader = null; + _loadStrategy = null; + _expressionCompiler = null; + } + + @override + Future recompile({required bool fullRestart}) async { + await webRunner.rerun( + fullRestart: fullRestart, + fileServerUri: Uri.parse('http://${testServer.host}:${testServer.port}'), + ); + } +} diff --git a/dwds/test/integration/frontend_server/README.md b/dwds/test/integration/frontend_server/README.md new file mode 100644 index 0000000000..54151ee90c --- /dev/null +++ b/dwds/test/integration/frontend_server/README.md @@ -0,0 +1,5 @@ +# Frontend Server Integration Tests + +The tests in this directory are wrappers around the shared integration test scenarios defined in `package:dwds_test_common/integration`. + +They execute the test scenarios defined there using `frontend_server` as the build client. diff --git a/dwds/test/integration/breakpoint_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/breakpoint_ddc_library_bundle_test.dart similarity index 69% rename from dwds/test/integration/breakpoint_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/breakpoint_ddc_library_bundle_test.dart index 71b4606d73..7353a86685 100644 --- a/dwds/test/integration/breakpoint_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/breakpoint_ddc_library_bundle_test.dart @@ -2,16 +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. -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/breakpoint.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'breakpoint_common.dart'; -import 'fixtures/context.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -24,17 +20,10 @@ void main() { ); tearDownAll(provider.dispose); - group('Build Daemon |', () { - testBreakpoint( - provider: provider, - compilationMode: CompilationMode.buildDaemon, - ); - }); - group('Frontend Server |', () { testBreakpoint( provider: provider, - compilationMode: CompilationMode.frontendServer, + contextFactory: FrontendServerTestContext.new, ); }); } diff --git a/dwds/test/integration/frontend_server/callstack_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/callstack_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..152acf421d --- /dev/null +++ b/dwds/test/integration/frontend_server/callstack_ddc_library_bundle_test.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2026, 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:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/callstack.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../fixtures/frontend_server_context.dart'; + +void main() { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Frontend Server |', () { + testCallStack( + provider: provider, + contextFactory: FrontendServerTestContext.new, + ); + }); +} diff --git a/dwds/test/integration/hot_restart_correctness_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/chrome_proxy_service_ddc_library_bundle_test.dart similarity index 55% rename from dwds/test/integration/hot_restart_correctness_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/chrome_proxy_service_ddc_library_bundle_test.dart index f5a1f6839f..b66dccc89c 100644 --- a/dwds/test/integration/hot_restart_correctness_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/chrome_proxy_service_ddc_library_bundle_test.dart @@ -2,17 +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. -@TestOn('vm') -@Tags(['daily']) -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/chrome_proxy_service.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'common/hot_restart_correctness_common.dart'; -import 'fixtures/context.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -26,26 +21,13 @@ void main() { canaryFeatures: canaryFeatures, ddcModuleFormat: moduleFormat, ); - final compilationMode = CompilationMode.frontendServer; - runTests( - provider: provider, - moduleFormat: moduleFormat, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); + final contextFactory = FrontendServerTestContext.new; + tearDownAll(provider.dispose); - group('canary: $canaryFeatures | Build Daemon |', () { - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: canaryFeatures, - ddcModuleFormat: moduleFormat, - ); - final compilationMode = CompilationMode.buildDaemon; runTests( provider: provider, moduleFormat: moduleFormat, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/frontend_server/circular_evaluate/circular_evaluate_ddc_library_bundle_base_test.dart b/dwds/test/integration/frontend_server/circular_evaluate/circular_evaluate_ddc_library_bundle_base_test.dart new file mode 100644 index 0000000000..f287d8cc95 --- /dev/null +++ b/dwds/test/integration/frontend_server/circular_evaluate/circular_evaluate_ddc_library_bundle_base_test.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2026, 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:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate_circular.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../fixtures/frontend_server_context.dart'; + +void main() async { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group( + 'Frontend Server | Context with circular dependencies | with base |', + () { + testAll( + provider: provider, + contextFactory: FrontendServerTestContext.new, + indexBaseMode: IndexBaseMode.base, + useDebuggerModuleNames: true, + ); + }, + ); +} diff --git a/dwds/test/integration/frontend_server/circular_evaluate/circular_evaluate_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/circular_evaluate/circular_evaluate_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..91e7b0f1a5 --- /dev/null +++ b/dwds/test/integration/frontend_server/circular_evaluate/circular_evaluate_ddc_library_bundle_test.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2026, 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:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate_circular.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../fixtures/frontend_server_context.dart'; + +void main() async { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group( + 'Frontend Server | Context with circular dependencies | with noBase |', + () { + testAll( + provider: provider, + contextFactory: FrontendServerTestContext.new, + indexBaseMode: IndexBaseMode.noBase, + useDebuggerModuleNames: true, + ); + }, + ); +} diff --git a/dwds/test/integration/frontend_server/dart_uri_file_uri_debugger_module_names_test.dart b/dwds/test/integration/frontend_server/dart_uri_file_uri_debugger_module_names_test.dart new file mode 100644 index 0000000000..a0f3ce9920 --- /dev/null +++ b/dwds/test/integration/frontend_server/dart_uri_file_uri_debugger_module_names_test.dart @@ -0,0 +1,18 @@ +// Copyright (c) 2026, 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:dwds_test_common/integration/dart_uri_file_uri_debugger_module_names.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../fixtures/frontend_server_context.dart'; + +void main() { + final provider = TestSdkConfigurationProvider(); + tearDownAll(provider.dispose); + + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/dwds/test/integration/frontend_server/dart_uri_file_uri_test.dart b/dwds/test/integration/frontend_server/dart_uri_file_uri_test.dart new file mode 100644 index 0000000000..ed6780f658 --- /dev/null +++ b/dwds/test/integration/frontend_server/dart_uri_file_uri_test.dart @@ -0,0 +1,18 @@ +// Copyright (c) 2019, 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:dwds_test_common/integration/dart_uri_file_uri.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../fixtures/frontend_server_context.dart'; + +void main() { + final provider = TestSdkConfigurationProvider(); + tearDownAll(provider.dispose); + + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/dwds/test/integration/debug_service_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/debug_service_ddc_library_bundle_test.dart similarity index 76% rename from dwds/test/integration/debug_service_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/debug_service_ddc_library_bundle_test.dart index 06fe831e68..b8bc15f88e 100644 --- a/dwds/test/integration/debug_service_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/debug_service_ddc_library_bundle_test.dart @@ -2,15 +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. -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/debug_service.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'debug_service_common.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -23,5 +20,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); } diff --git a/dwds/test/integration/devtools_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/devtools_ddc_library_bundle_test.dart similarity index 73% rename from dwds/test/integration/devtools_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/devtools_ddc_library_bundle_test.dart index b6ad5bbaf2..abdd2178bc 100644 --- a/dwds/test/integration/devtools_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/devtools_ddc_library_bundle_test.dart @@ -2,15 +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. -@Timeout(Duration(minutes: 5)) -@TestOn('vm') -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/devtools.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'devtools_common.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { final provider = TestSdkConfigurationProvider( @@ -19,5 +16,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); } diff --git a/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_base_test.dart b/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_base_test.dart new file mode 100644 index 0000000000..27a1dc77e5 --- /dev/null +++ b/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_base_test.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2026, 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:io'; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../fixtures/frontend_server_context.dart'; + +void main() async { + // Enable verbose logging for debugging. + const debug = false; + + group('Canary: true |', () { + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Frontend Server | Debugger module names: false | with base |', () { + testAll( + provider: provider, + contextFactory: FrontendServerTestContext.new, + indexBaseMode: IndexBaseMode.base, + useDebuggerModuleNames: false, + ); + }, skip: Platform.isWindows ? 'Skipped on Windows' : null); + }); +} diff --git a/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_debugger_module_names_base_test.dart b/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_debugger_module_names_base_test.dart new file mode 100644 index 0000000000..aad8e8d988 --- /dev/null +++ b/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_debugger_module_names_base_test.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2026, 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:io'; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../fixtures/frontend_server_context.dart'; + +void main() async { + // Enable verbose logging for debugging. + const debug = false; + + group('Canary: true |', () { + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Frontend Server | Debugger module names: true | with base |', () { + testAll( + provider: provider, + contextFactory: FrontendServerTestContext.new, + indexBaseMode: IndexBaseMode.base, + useDebuggerModuleNames: true, + ); + }, skip: Platform.isWindows ? 'Skipped on Windows' : null); + }); +} diff --git a/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_debugger_module_names_test.dart b/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_debugger_module_names_test.dart new file mode 100644 index 0000000000..042354880d --- /dev/null +++ b/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_debugger_module_names_test.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2026, 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:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../fixtures/frontend_server_context.dart'; + +void main() async { + // Enable verbose logging for debugging. + const debug = false; + + group('Canary: true |', () { + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Frontend Server | Debugger module names: true | with noBase |', () { + testAll( + provider: provider, + contextFactory: FrontendServerTestContext.new, + indexBaseMode: IndexBaseMode.noBase, + useDebuggerModuleNames: true, + ); + }); + }); +} diff --git a/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..1d8953e27d --- /dev/null +++ b/dwds/test/integration/frontend_server/evaluate/evaluate_ddc_library_bundle_test.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2026, 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:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../fixtures/frontend_server_context.dart'; + +void main() async { + // Enable verbose logging for debugging. + const debug = false; + + group('Canary: true |', () { + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Frontend Server | Debugger module names: false | with noBase |', () { + testAll( + provider: provider, + contextFactory: FrontendServerTestContext.new, + indexBaseMode: IndexBaseMode.noBase, + useDebuggerModuleNames: false, + ); + }); + }); +} diff --git a/dwds/test/integration/hot_reload_breakpoints_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/events_ddc_library_bundle_test.dart similarity index 73% rename from dwds/test/integration/hot_reload_breakpoints_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/events_ddc_library_bundle_test.dart index d0494e7400..d29dc2c1ce 100644 --- a/dwds/test/integration/hot_reload_breakpoints_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/events_ddc_library_bundle_test.dart @@ -2,33 +2,28 @@ // 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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 5)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/events.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'fixtures/context.dart'; -import 'hot_reload_breakpoints_common.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. const debug = false; + final canary = true; final provider = TestSdkConfigurationProvider( verbose: debug, - canaryFeatures: true, + canaryFeatures: canary, ddcModuleFormat: ModuleFormat.ddc, ); - tearDownAll(provider.dispose); group('Frontend Server', () { - runTests( + testWithDwds( provider: provider, - compilationMode: CompilationMode.frontendServer, + contextFactory: FrontendServerTestContext.new, ); }); } diff --git a/dwds/test/integration/frontend_server/hot_reload_breakpoints_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/hot_reload_breakpoints_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..e5a82e148c --- /dev/null +++ b/dwds/test/integration/frontend_server/hot_reload_breakpoints_ddc_library_bundle_test.dart @@ -0,0 +1,26 @@ +// Copyright (c) 2026, 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:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/hot_reload_breakpoints.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../fixtures/frontend_server_context.dart'; + +void main() { + // Enable verbose logging for debugging. + const debug = false; + final provider = TestSdkConfigurationProvider( + verbose: debug, + canaryFeatures: true, + ddcModuleFormat: ModuleFormat.ddc, + ); + + tearDownAll(provider.dispose); + + group('Frontend Server', () { + runTests(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/dwds/test/integration/hot_reload_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/hot_reload_ddc_library_bundle_test.dart similarity index 73% rename from dwds/test/integration/hot_reload_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/hot_reload_ddc_library_bundle_test.dart index ba5923935f..6c64f6a0a4 100644 --- a/dwds/test/integration/hot_reload_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/hot_reload_ddc_library_bundle_test.dart @@ -2,17 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 5)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/hot_reload.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'fixtures/context.dart'; -import 'hot_reload_common.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -26,9 +21,6 @@ void main() { tearDownAll(provider.dispose); group('Frontend Server', () { - runTests( - provider: provider, - compilationMode: CompilationMode.frontendServer, - ); + runTests(provider: provider, contextFactory: FrontendServerTestContext.new); }); } diff --git a/dwds/test/integration/hot_restart_breakpoints_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/hot_restart_breakpoints_ddc_library_bundle_test.dart similarity index 64% rename from dwds/test/integration/hot_restart_breakpoints_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/hot_restart_breakpoints_ddc_library_bundle_test.dart index 364a4112d4..5aa1ba09e2 100644 --- a/dwds/test/integration/hot_restart_breakpoints_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/hot_restart_breakpoints_ddc_library_bundle_test.dart @@ -2,17 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 5)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/hot_restart_breakpoints.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'fixtures/context.dart'; -import 'hot_restart_breakpoints_common.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -26,13 +21,6 @@ void main() { tearDownAll(provider.dispose); group('Frontend Server', () { - runTests( - provider: provider, - compilationMode: CompilationMode.frontendServer, - ); - }); - - group('Build Daemon', () { - runTests(provider: provider, compilationMode: CompilationMode.buildDaemon); + runTests(provider: provider, contextFactory: FrontendServerTestContext.new); }); } diff --git a/dwds/test/integration/chrome_proxy_service_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/hot_restart_correctness_ddc_library_bundle_test.dart similarity index 52% rename from dwds/test/integration/chrome_proxy_service_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/hot_restart_correctness_ddc_library_bundle_test.dart index fa577f8939..11a043feea 100644 --- a/dwds/test/integration/chrome_proxy_service_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/hot_restart_correctness_ddc_library_bundle_test.dart @@ -2,17 +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. -@TestOn('vm') -@Tags(['daily']) -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/hot_restart_correctness.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'common/chrome_proxy_service_common.dart'; -import 'fixtures/context.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -26,30 +21,11 @@ void main() { canaryFeatures: canaryFeatures, ddcModuleFormat: moduleFormat, ); - final compilationMode = CompilationMode.frontendServer; - tearDownAll(provider.dispose); - - runTests( - provider: provider, - moduleFormat: moduleFormat, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); - - group('canary: $canaryFeatures | Build Daemon |', () { - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: canaryFeatures, - ddcModuleFormat: moduleFormat, - ); - final compilationMode = CompilationMode.buildDaemon; - tearDownAll(provider.dispose); - + final contextFactory = FrontendServerTestContext.new; runTests( provider: provider, moduleFormat: moduleFormat, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/hot_restart_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/hot_restart_ddc_library_bundle_test.dart similarity index 55% rename from dwds/test/integration/hot_restart_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/hot_restart_ddc_library_bundle_test.dart index dacc2f86e7..f50aea379d 100644 --- a/dwds/test/integration/hot_restart_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/hot_restart_ddc_library_bundle_test.dart @@ -2,17 +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. -@TestOn('vm') -@Tags(['daily']) -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/hot_restart.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'common/hot_restart_common.dart'; -import 'fixtures/context.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -21,23 +16,7 @@ void main() { final moduleFormat = ModuleFormat.ddc; group('canary: $canaryFeatures | Frontend Server |', () { - final compilationMode = CompilationMode.frontendServer; - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: canaryFeatures, - ddcModuleFormat: moduleFormat, - ); - - runTests( - provider: provider, - moduleFormat: moduleFormat, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); - - group('canary: $canaryFeatures | Build Daemon |', () { - final compilationMode = CompilationMode.buildDaemon; + final contextFactory = FrontendServerTestContext.new; final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,7 +26,7 @@ void main() { runTests( provider: provider, moduleFormat: moduleFormat, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/class_inspection_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/instances/class_inspection_ddc_library_bundle_test.dart similarity index 53% rename from dwds/test/integration/instances/class_inspection_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/instances/class_inspection_ddc_library_bundle_test.dart index 77a97d66cd..6be1c8c8ca 100644 --- a/dwds/test/integration/instances/class_inspection_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/instances/class_inspection_ddc_library_bundle_test.dart @@ -2,17 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/class_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/class_inspection_common.dart'; +import '../../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,24 +15,7 @@ void main() { group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: canaryFeatures, - ddcModuleFormat: ModuleFormat.ddc, - ); - tearDownAll(provider.dispose); - - runTests( - provider: provider, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); - - group('canary: true | Build Daemon |', () { - final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final contextFactory = FrontendServerTestContext.new; final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,7 +25,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/dot_shorthands_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/instances/dot_shorthands_ddc_library_bundle_test.dart similarity index 53% rename from dwds/test/integration/instances/dot_shorthands_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/instances/dot_shorthands_ddc_library_bundle_test.dart index 3559490635..21e3ed2c69 100644 --- a/dwds/test/integration/instances/dot_shorthands_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/instances/dot_shorthands_ddc_library_bundle_test.dart @@ -2,17 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds_test_common/integration/dot_shorthands.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/dot_shorthands_common.dart'; +import '../../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,24 +15,7 @@ void main() { group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: canaryFeatures, - ddcModuleFormat: ModuleFormat.ddc, - ); - tearDownAll(provider.dispose); - - runTests( - provider: provider, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); - - group('canary: true | Build Daemon |', () { - final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final contextFactory = FrontendServerTestContext.new; final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,7 +25,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/instance_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/instances/instance_ddc_library_bundle_test.dart similarity index 56% rename from dwds/test/integration/instances/instance_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/instances/instance_ddc_library_bundle_test.dart index 002c71c57e..f594032d90 100644 --- a/dwds/test/integration/instances/instance_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/instances/instance_ddc_library_bundle_test.dart @@ -2,16 +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. -@Tags(['daily']) -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds_test_common/integration/instance.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/instance_common.dart'; +import '../../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,23 +16,7 @@ void main() { final moduleFormat = ModuleFormat.ddc; group('canary: true | Frontend Server |', () { - final compilationMode = CompilationMode.frontendServer; - final provider = TestSdkConfigurationProvider( - canaryFeatures: canaryFeatures, - verbose: debug, - ddcModuleFormat: moduleFormat, - ); - tearDownAll(provider.dispose); - - runTests( - provider: provider, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); - - group('canary: true | Build Daemon |', () { - final compilationMode = CompilationMode.buildDaemon; + final contextFactory = FrontendServerTestContext.new; final provider = TestSdkConfigurationProvider( canaryFeatures: canaryFeatures, verbose: debug, @@ -46,7 +26,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/instance_inspection_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/instances/instance_inspection_ddc_library_bundle_test.dart similarity index 76% rename from dwds/test/integration/instances/instance_inspection_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/instances/instance_inspection_ddc_library_bundle_test.dart index 93e375d548..fb605dbbc9 100644 --- a/dwds/test/integration/instances/instance_inspection_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/instances/instance_inspection_ddc_library_bundle_test.dart @@ -2,17 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds_test_common/integration/instance_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/instance_inspection_common.dart'; +import '../../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,7 +15,7 @@ void main() { group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; + final contextFactory = FrontendServerTestContext.new; final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -30,7 +25,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/patterns_inspection_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/instances/patterns_inspection_ddc_library_bundle_test.dart similarity index 53% rename from dwds/test/integration/instances/patterns_inspection_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/instances/patterns_inspection_ddc_library_bundle_test.dart index e9a5e0fd96..d85f447b95 100644 --- a/dwds/test/integration/instances/patterns_inspection_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/instances/patterns_inspection_ddc_library_bundle_test.dart @@ -2,17 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/patterns_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/patterns_inspection_common.dart'; +import '../../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,24 +15,7 @@ void main() { group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: canaryFeatures, - ddcModuleFormat: ModuleFormat.ddc, - ); - tearDownAll(provider.dispose); - - runTests( - provider: provider, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); - - group('canary: true | Build Daemon |', () { - final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final contextFactory = FrontendServerTestContext.new; final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,7 +25,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/record_inspection_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/instances/record_inspection_ddc_library_bundle_test.dart similarity index 54% rename from dwds/test/integration/instances/record_inspection_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/instances/record_inspection_ddc_library_bundle_test.dart index 0201c28224..873f43dde9 100644 --- a/dwds/test/integration/instances/record_inspection_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/instances/record_inspection_ddc_library_bundle_test.dart @@ -2,17 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds_test_common/integration/record_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/record_inspection_common.dart'; +import '../../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,22 +15,7 @@ void main() { final canaryFeatures = true; group('canary: true | Frontend Server |', () { - final compilationMode = CompilationMode.frontendServer; - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: canaryFeatures, - ddcModuleFormat: ModuleFormat.ddc, - ); - tearDownAll(provider.dispose); - runTests( - provider: provider, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); - - group('canary: true | Build Daemon |', () { - final compilationMode = CompilationMode.buildDaemon; + final contextFactory = FrontendServerTestContext.new; final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -44,7 +24,7 @@ void main() { tearDownAll(provider.dispose); runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/record_type_inspection_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/instances/record_type_inspection_ddc_library_bundle_test.dart similarity index 54% rename from dwds/test/integration/instances/record_type_inspection_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/instances/record_type_inspection_ddc_library_bundle_test.dart index 3832869b73..3ac81fb59c 100644 --- a/dwds/test/integration/instances/record_type_inspection_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/instances/record_type_inspection_ddc_library_bundle_test.dart @@ -2,17 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/record_type_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/record_type_inspection_common.dart'; +import '../../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,22 +15,7 @@ void main() { final canaryFeatures = true; group('canary: true | Frontend Server |', () { - final compilationMode = CompilationMode.frontendServer; - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: canaryFeatures, - ddcModuleFormat: ModuleFormat.ddc, - ); - tearDownAll(provider.dispose); - runTests( - provider: provider, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); - - group('canary: true | Build Daemon |', () { - final compilationMode = CompilationMode.buildDaemon; + final contextFactory = FrontendServerTestContext.new; final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -44,7 +24,7 @@ void main() { tearDownAll(provider.dispose); runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/type_inspection_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/instances/type_inspection_ddc_library_bundle_test.dart similarity index 53% rename from dwds/test/integration/instances/type_inspection_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/instances/type_inspection_ddc_library_bundle_test.dart index 3756541e0e..89dcaea777 100644 --- a/dwds/test/integration/instances/type_inspection_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/instances/type_inspection_ddc_library_bundle_test.dart @@ -2,17 +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. -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/type_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/type_inspection_common.dart'; +import '../../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,24 +15,7 @@ void main() { group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: canaryFeatures, - ddcModuleFormat: ModuleFormat.ddc, - ); - tearDownAll(provider.dispose); - - runTests( - provider: provider, - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - ); - }); - - group('canary: true | Build Daemon |', () { - final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final contextFactory = FrontendServerTestContext.new; final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,7 +25,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: contextFactory, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/frontend_server/listviews_test.dart b/dwds/test/integration/frontend_server/listviews_test.dart new file mode 100644 index 0000000000..e417b7628a --- /dev/null +++ b/dwds/test/integration/frontend_server/listviews_test.dart @@ -0,0 +1,18 @@ +// 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:dwds_test_common/integration/listviews.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../fixtures/frontend_server_context.dart'; + +void main() { + final provider = TestSdkConfigurationProvider(); + tearDownAll(provider.dispose); + + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/dwds/test/integration/frontend_server/load_strategy_test.dart b/dwds/test/integration/frontend_server/load_strategy_test.dart new file mode 100644 index 0000000000..cfe4799ad0 --- /dev/null +++ b/dwds/test/integration/frontend_server/load_strategy_test.dart @@ -0,0 +1,18 @@ +// 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:dwds_test_common/integration/load_strategy.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../fixtures/frontend_server_context.dart'; + +void main() { + final provider = TestSdkConfigurationProvider(); + tearDownAll(provider.dispose); + + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/dwds/test/integration/frontend_server/parts_evaluate/parts_evaluate_ddc_library_bundle_base_test.dart b/dwds/test/integration/frontend_server/parts_evaluate/parts_evaluate_ddc_library_bundle_base_test.dart new file mode 100644 index 0000000000..23237f0f37 --- /dev/null +++ b/dwds/test/integration/frontend_server/parts_evaluate/parts_evaluate_ddc_library_bundle_base_test.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2026, 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:io'; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate_parts.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../fixtures/frontend_server_context.dart'; + +void main() async { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Frontend Server | Context with part files | with base |', () { + testAll( + provider: provider, + contextFactory: FrontendServerTestContext.new, + indexBaseMode: IndexBaseMode.base, + useDebuggerModuleNames: true, + ); + }, skip: Platform.isWindows ? 'Skipped on Windows' : null); +} diff --git a/dwds/test/integration/frontend_server/parts_evaluate/parts_evaluate_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/parts_evaluate/parts_evaluate_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..f8ce05ed89 --- /dev/null +++ b/dwds/test/integration/frontend_server/parts_evaluate/parts_evaluate_ddc_library_bundle_test.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2026, 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:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate_parts.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../fixtures/frontend_server_context.dart'; + +void main() async { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Frontend Server | Context with part files | with noBase |', () { + testAll( + provider: provider, + contextFactory: FrontendServerTestContext.new, + indexBaseMode: IndexBaseMode.noBase, + useDebuggerModuleNames: true, + ); + }); +} diff --git a/dwds/test/integration/refresh_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/refresh_ddc_library_bundle_test.dart similarity index 70% rename from dwds/test/integration/refresh_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/refresh_ddc_library_bundle_test.dart index 6820f6421b..c44adc510a 100644 --- a/dwds/test/integration/refresh_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/refresh_ddc_library_bundle_test.dart @@ -2,17 +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. -/// Tests that require a fresh context to run, and can interfere with other -/// tests. -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; +// Tests that require a fresh context to run, and can interfere with other +// tests. import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/refresh.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'refresh_common.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -26,5 +24,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); } diff --git a/dwds/test/integration/run_request_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/run_request_ddc_library_bundle_test.dart similarity index 76% rename from dwds/test/integration/run_request_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/run_request_ddc_library_bundle_test.dart index 4e51bb3b5d..72e0ee9ac9 100644 --- a/dwds/test/integration/run_request_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/run_request_ddc_library_bundle_test.dart @@ -2,14 +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. -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/run_request.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'run_request_common.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -22,5 +20,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); } diff --git a/dwds/test/integration/screenshot_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/screenshot_ddc_library_bundle_test.dart similarity index 77% rename from dwds/test/integration/screenshot_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/screenshot_ddc_library_bundle_test.dart index 0fc43cb1b0..49c897143f 100644 --- a/dwds/test/integration/screenshot_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/screenshot_ddc_library_bundle_test.dart @@ -2,14 +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. -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/screenshot.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'screenshot_common.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -23,5 +21,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); } diff --git a/dwds/test/integration/variable_scope_ddc_library_bundle_test.dart b/dwds/test/integration/frontend_server/variable_scope_ddc_library_bundle_test.dart similarity index 76% rename from dwds/test/integration/variable_scope_ddc_library_bundle_test.dart rename to dwds/test/integration/frontend_server/variable_scope_ddc_library_bundle_test.dart index e5a4963ef7..28d5e8fa2f 100644 --- a/dwds/test/integration/variable_scope_ddc_library_bundle_test.dart +++ b/dwds/test/integration/frontend_server/variable_scope_ddc_library_bundle_test.dart @@ -2,15 +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. -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/variable_scope.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'variable_scope_common.dart'; +import '../fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -24,5 +21,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); } diff --git a/dwds/test/integration/handlers/injector_test.dart b/dwds/test/integration/handlers/injector_test.dart index b791deaa7c..9d887c119e 100644 --- a/dwds/test/integration/handlers/injector_test.dart +++ b/dwds/test/integration/handlers/injector_test.dart @@ -9,13 +9,12 @@ import 'dart:io'; import 'package:dwds/src/handlers/injector.dart'; import 'package:dwds/src/version.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:http/http.dart' as http; import 'package:shelf/shelf.dart'; import 'package:shelf/shelf_io.dart' as shelf_io; import 'package:test/test.dart'; -import '../fixtures/utilities.dart'; - void main() { late HttpServer server; const entryEtag = 'entry etag'; diff --git a/dwds/test/integration/location_test.dart b/dwds/test/integration/location_test.dart index e3a9143204..6c81acf079 100644 --- a/dwds/test/integration/location_test.dart +++ b/dwds/test/integration/location_test.dart @@ -7,11 +7,10 @@ library; import 'package:dwds/src/debugging/location.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; +import 'package:dwds_test_common/fixtures/fakes.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:test/test.dart'; -import 'fixtures/fakes.dart'; -import 'fixtures/utilities.dart'; - final sourceMapContents = '{"version":3,"sourceRoot":"","sources":["main.dart"],"names":[],' '"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUwB,IAAtB,WAAM;AAKJ,' diff --git a/dwds/test/integration/metadata_test.dart b/dwds/test/integration/metadata_test.dart index 50d12c8e1d..a02797a926 100644 --- a/dwds/test/integration/metadata_test.dart +++ b/dwds/test/integration/metadata_test.dart @@ -9,11 +9,10 @@ import 'dart:convert'; import 'package:dwds/src/debugging/metadata/module_metadata.dart'; import 'package:dwds/src/debugging/metadata/provider.dart'; +import 'package:dwds_test_common/fixtures/fakes.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:test/test.dart'; -import 'fixtures/fakes.dart'; -import 'fixtures/utilities.dart'; - const _emptySourceMetadata = '{"version":"1.0.0","name":"web/main","closureName":"load__web__main",' '"sourceMapUri":"foo/web/main.ddc.js.map",' diff --git a/dwds/test/integration/package_uri_mapper_test.dart b/dwds/test/integration/package_uri_mapper_test.dart index 8d8e8957ac..c27ef513ee 100644 --- a/dwds/test/integration/package_uri_mapper_test.dart +++ b/dwds/test/integration/package_uri_mapper_test.dart @@ -9,12 +9,11 @@ library; import 'dart:io'; import 'package:dwds/dwds.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; import 'package:file/local.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; -import 'fixtures/project.dart'; - void main() { final project = TestProject.testPackage(); diff --git a/dwds/test/integration/parts_evaluate_ddc_library_bundle_test.dart b/dwds/test/integration/parts_evaluate_ddc_library_bundle_test.dart deleted file mode 100644 index d99e21b65a..0000000000 --- a/dwds/test/integration/parts_evaluate_ddc_library_bundle_test.dart +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2026, 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. - -@Tags(['daily']) -@TestOn('vm') -@Timeout(Duration(minutes: 5)) -library; - -import 'dart:io'; - -import 'package:dwds/expression_compiler.dart'; -import 'package:dwds_test_common/test_sdk_configuration.dart'; -import 'package:test/test.dart'; - -import 'evaluate_parts_common.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; - -void main() async { - // Enable verbose logging for debugging. - const debug = false; - - final provider = TestSdkConfigurationProvider( - verbose: debug, - ddcModuleFormat: ModuleFormat.ddc, - canaryFeatures: true, - ); - tearDownAll(provider.dispose); - - group('Build Daemon |', () { - testAll(provider: provider, compilationMode: CompilationMode.buildDaemon); - }); - - group('Frontend Server |', () { - group('Context with parts |', () { - for (final indexBaseMode in IndexBaseMode.values) { - group( - 'with ${indexBaseMode.name} |', - () { - testAll( - provider: provider, - compilationMode: CompilationMode.frontendServer, - indexBaseMode: indexBaseMode, - useDebuggerModuleNames: true, - ); - }, - skip: - // https://github.com/dart-lang/sdk/issues/49277 - indexBaseMode == IndexBaseMode.base && Platform.isWindows, - ); - } - }); - }); -} diff --git a/dwds/test/integration/readers/frontend_server_asset_reader_test.dart b/dwds/test/integration/readers/frontend_server_asset_reader_test.dart index e6a57931aa..21620acdf9 100644 --- a/dwds/test/integration/readers/frontend_server_asset_reader_test.dart +++ b/dwds/test/integration/readers/frontend_server_asset_reader_test.dart @@ -8,15 +8,14 @@ library; import 'dart:io'; import 'package:dwds/src/readers/frontend_server_asset_reader.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; import 'package:dwds_test_common/test_sdk_layout.dart'; import 'package:dwds_test_common/utilities.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; -import '../fixtures/project.dart'; - final fixturesDir = absolutePath( - pathFromDwds: p.join('test', 'integration', 'fixtures'), + pathFromWebdev: p.join('dwds_test_common', 'lib', 'fixtures'), ); void main() { diff --git a/dwds/test/integration/skip_list_test.dart b/dwds/test/integration/skip_list_test.dart index 55ed079ec9..e8355c12ec 100644 --- a/dwds/test/integration/skip_list_test.dart +++ b/dwds/test/integration/skip_list_test.dart @@ -8,11 +8,10 @@ library; import 'package:dwds/src/debugging/location.dart'; import 'package:dwds/src/debugging/skip_list.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:source_maps/parser.dart'; import 'package:test/test.dart'; -import 'fixtures/utilities.dart'; - void main() { setGlobalsForTesting(); late SkipLists skipLists; diff --git a/dwds/test/integration/utilities_test.dart b/dwds/test/integration/utilities_test.dart index 83231ea955..a2e43ec42e 100644 --- a/dwds/test/integration/utilities_test.dart +++ b/dwds/test/integration/utilities_test.dart @@ -6,11 +6,10 @@ library; import 'package:dwds/src/utilities/shared.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import 'fixtures/context.dart'; - void main() { group('wrapInErrorHandlerAsync', () { test('returns future success value if callback succeeds', () async { diff --git a/dwds_test_common/analysis_options.yaml b/dwds_test_common/analysis_options.yaml index 3faabb59de..90e085774b 100644 --- a/dwds_test_common/analysis_options.yaml +++ b/dwds_test_common/analysis_options.yaml @@ -1,5 +1,8 @@ include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: + errors: + implementation_imports: ignore + prefer_relative_imports: ignore exclude: - fixtures/** diff --git a/dwds_test_common/fixtures/_test/example/scopes/main.dart b/dwds_test_common/fixtures/_test/example/scopes/main.dart index 4b21bd5928..440cea936e 100644 --- a/dwds_test_common/fixtures/_test/example/scopes/main.dart +++ b/dwds_test_common/fixtures/_test/example/scopes/main.dart @@ -25,6 +25,8 @@ final stream = Stream.value(1); MyTestClass getLibraryPublicFinal() => libraryPublicFinal; +List getLibraryPrivate() => _libraryPrivate; + List getLibraryPublic() => libraryPublic; Map getMap() => map; diff --git a/dwds_test_common/lib/fixtures/context.dart b/dwds_test_common/lib/fixtures/context.dart new file mode 100644 index 0000000000..dff445db75 --- /dev/null +++ b/dwds_test_common/lib/fixtures/context.dart @@ -0,0 +1,749 @@ +// Copyright (c) 2019, 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 'dart:io'; +import 'dart:isolate' as isolate show Isolate; + +import 'package:dwds/asset_reader.dart'; +import 'package:dwds/dart_web_debug_service.dart'; +import 'package:dwds/data/build_result.dart'; +import 'package:dwds/src/connections/app_connection.dart'; +import 'package:dwds/src/connections/debug_connection.dart'; +import 'package:dwds/src/debugging/webkit_debugger.dart'; +import 'package:dwds/src/loaders/strategy.dart'; +import 'package:dwds/src/services/chrome/chrome_proxy_service.dart'; +import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds/src/utilities/dart_uri.dart'; +import 'package:dwds/src/utilities/server.dart'; +import 'package:http/http.dart'; +import 'package:http/io_client.dart'; +import 'package:http/retry.dart'; +import 'package:logging/logging.dart' as logging; +import 'package:path/path.dart' as p; +import 'package:shelf/shelf.dart' as shelf; +import 'package:shelf/shelf.dart'; +import 'package:test/test.dart'; +import 'package:vm_service/vm_service.dart'; +import 'package:vm_service/vm_service_io.dart'; +import 'package:webdriver/async_io.dart'; +import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; + +import '../logging.dart'; +import '../test_sdk_configuration.dart'; +import '../utilities.dart'; +import 'project.dart'; +import 'server.dart'; +import 'utilities.dart'; + +const isRPCError = TypeMatcher(); +const isSentinelException = TypeMatcher(); + +final Matcher throwsRPCError = throwsA(isRPCError); +final Matcher throwsSentinelException = throwsA(isSentinelException); + +Matcher isRPCErrorWithMessage(String message) => isA().having( + (RPCError e) => e.message, + 'message', + contains(message), +); +Matcher throwsRPCErrorWithMessage(String message) => + throwsA(isRPCErrorWithMessage(message)); + +Matcher isRPCErrorWithCode(int code) => + isA().having((RPCError e) => e.code, 'code', equals(code)); +Matcher throwsRPCErrorWithCode(int code) => throwsA(isRPCErrorWithCode(code)); + +typedef TestContextFactory = + TestContext Function(TestProject, TestSdkConfigurationProvider); + +abstract class TestContext { + static const reloadedSourcesFileName = 'reloaded_sources.json'; + + final TestProject project; + final TestSdkConfigurationProvider sdkConfigurationProvider; + + String get appUrl => _appUrl!; + late String? _appUrl; + + WipConnection get tabConnection => _tabConnection!; + late WipConnection? _tabConnection; + + TestServer get testServer => _testServer!; + TestServer? _testServer; + + Dwds? get dwds => _testServer?.dwds; + + WebDriver get webDriver => _webDriver!; + WebDriver? _webDriver; + + Process get chromeDriver => _chromeDriver!; + Process? _chromeDriver; + + WebkitDebugger get webkitDebugger => _webkitDebugger!; + late WebkitDebugger? _webkitDebugger; + + Client get client => _client!; + Client? _client; + + int get port => _port!; + late int? _port; + + Directory get outputDir => _outputDir!; + Directory? _outputDir; + + late WipConnection extensionConnection; + late AppConnection appConnection; + late DebugConnection debugConnection; + + final _logger = logging.Logger('Context'); + + final _serviceNameToMethod = {}; + + /// Internal VM service. + /// + /// Prefer using [vmService] instead in tests when possible, to include + /// testing of the VmServerConnection (bypassed when using [service]). + ChromeProxyService get service => fetchChromeProxyService(debugConnection); + + /// External VM service. + VmService get vmService => debugConnection.vmService; + + TestContext.protected(this.project, this.sdkConfigurationProvider); + + bool get usesFrontendServer => false; + bool get usesBuildDaemon => false; + bool get usesDdcModulesOnly => false; + + // Abstract members: + AssetReader get assetReader; + Handler get assetHandler; + LoadStrategy get loadStrategy; + Stream get buildResults; + ExpressionCompiler? get expressionCompiler; + + String get appUrlPath; + String get basePath => ''; + + Future modeSetUp( + TestSettings testSettings, + TestDebugSettings debugSettings, + TestAppMetadata appMetadata, + Uri reloadedSourcesUri, + ); + + Future modeTearDown(); + + String get chromeDriverExecutable => _resolveChromeDriverExecutable(); + String get chromeExecutable => _resolveChromeExecutable(); + + Future setUp({ + TestSettings testSettings = const TestSettings(), + TestAppMetadata appMetadata = const TestAppMetadata.externalApp(), + TestDebugSettings debugSettings = + const TestDebugSettings.noDevToolsLaunch(), + }) async { + try { + // Make sure configuration was created correctly. + final sdkLayout = sdkConfigurationProvider.sdkLayout; + final configuration = await sdkConfigurationProvider.configuration; + configuration.validate(); + await project.setUp(); + + DartUri.currentDirectory = project.absolutePackageDirectory; + + _logger.info( + 'Serving: ${project.directoryToServe}/${project.filePathToServe}', + ); + _logger.info('Project: ${project.absolutePackageDirectory}'); + _logger.info('Packages: ${project.packageConfigFile}'); + _logger.info('Entry: ${project.dartEntryFilePath}'); + + configureLogWriter(); + + _client = RetryClient( + IOClient( + HttpClient() + ..maxConnectionsPerHost = 200 + ..idleTimeout = const Duration(seconds: 30) + ..connectionTimeout = const Duration(seconds: 30), + ), + whenError: (error, stackTrace) { + _logger.warning('Retrying request due to network error: $error'); + return true; + }, + ); + + final systemTempDir = Directory.systemTemp; + _outputDir = systemTempDir.createTempSync('foo bar'); + + final sharedChromeDriverPort = + Platform.environment['DWDS_CHROMEDRIVER_PORT']; + final chromeDriverPort = sharedChromeDriverPort != null + ? int.parse(sharedChromeDriverPort) + : await findUnusedPort(); + final chromeDriverUrlBase = 'wd/hub'; + if (sharedChromeDriverPort == null) { + try { + _chromeDriver = await Process.start(chromeDriverExecutable, [ + '--port=$chromeDriverPort', + '--url-base=$chromeDriverUrlBase', + ]); + final stdOutLines = chromeDriver.stdout + .transform(utf8.decoder) + .transform(const LineSplitter()) + .asBroadcastStream(); + + final stdErrLines = chromeDriver.stderr + .transform(utf8.decoder) + .transform(const LineSplitter()) + .asBroadcastStream(); + + final chromeDriverStartup = Completer(); + stdOutLines.listen((line) { + if (!chromeDriverStartup.isCompleted && + line.contains('was started successfully')) { + chromeDriverStartup.complete(); + } + _logger.finest('ChromeDriver stdout: $line'); + }); + stdErrLines.listen( + (line) => _logger.warning('ChromeDriver stderr: $line'), + ); + + await chromeDriverStartup.future; + } catch (e) { + throw StateError( + 'Could not start ChromeDriver. Is it installed?\nError: $e', + ); + } + } + + final packageConfig = File( + p.join( + project.absolutePackageDirectory, + '.dart_tool', + 'package_config.json', + ), + ); + if (!packageConfig.existsSync()) { + await Process.run(sdkLayout.dartPath, [ + 'pub', + 'upgrade', + ], workingDirectory: project.absolutePackageDirectory); + } + + // Start the HTTP server and save its used port. + final httpServer = await startHttpServer('localhost'); + _port = httpServer.port; + + final reloadedSourcesUri = Uri.parse( + 'http://localhost:$_port/$reloadedSourcesFileName', + ); + + await modeSetUp( + testSettings, + debugSettings, + appMetadata, + reloadedSourcesUri, + ); + + final debugPort = await findUnusedPort(); + if (testSettings.launchChrome) { + // If the environment variable DWDS_DEBUG_CHROME is set to the string + // true then Chrome will be launched with a UI rather than headless. + // If the extension is enabled, then Chrome will be launched with a UI + // since headless Chrome does not support extensions. + final enableDebugExtension = debugSettings.enableDebugExtension; + final headless = + Platform.environment['DWDS_DEBUG_CHROME'] != 'true' && + !enableDebugExtension; + if (enableDebugExtension) { + await _buildDebugExtension(); + } + final capabilities = {...Capabilities.chrome} + ..addAll({ + Capabilities.chromeOptions: { + 'args': [ + // --disable-gpu speeds up the tests that use ChromeDriver when + // they are run on GitHub Actions. + '--disable-gpu', + 'remote-debugging-port=$debugPort', + if (enableDebugExtension) + '--load-extension=debug_extension/prod_build', + if (headless) '--headless', + // When the DevTools has focus we don't want to slow down the + // application. + '--disable-background-timer-throttling', + '--disable-blink-features=TimerThrottlingForBackgroundTabs', + '--disable-features=IntensiveWakeUpThrottling', + // Since we are using a temp profile, disable features that slow + // the Chrome launch. + '--disable-extensions', + '--disable-popup-blocking', + '--bwsi', + '--no-first-run', + '--no-default-browser-check', + '--disable-default-apps', + '--disable-translate', + '--start-maximized', + // When running on MacOS, Chrome may open system dialogs + // requesting credentials. This uses a mock keychain to avoid + // that dialog from blocking. + '--use-mock-keychain', + // Prevent warnings for using flags that are not recommended for + // general browsing but are applicable for use in dev-focused + // workflows. + '--test-type', + // Dev runs of the browser should be considered independent of + // one another, don't announce when the previous session + // crashed. + '--disable-session-crashed-bubble', + '--no-sandbox', + ], + 'binary': chromeExecutable, + }, + }); + _webDriver = await _createDriverWithRetry( + capabilities: capabilities, + uri: Uri.parse( + 'http://127.0.0.1:$chromeDriverPort/$chromeDriverUrlBase/', + ), + ); + } + + // The debugger tab must be enabled and connected before certain + // listeners in DWDS or `main` is run. + final tabConnectionCompleter = Completer(); + final appConnectionCompleter = Completer(); + final connection = ChromeConnection('localhost', debugPort); + + _testServer = await TestServer.start( + debugSettings: debugSettings.copyWith( + expressionCompiler: expressionCompiler, + ), + appMetadata: appMetadata, + port: port, + assetHandler: assetHandler, + assetReader: assetReader, + strategy: loadStrategy, + buildResults: buildResults, + chromeConnection: () async => connection, + httpServer: httpServer, + ); + + _testServer!.dwds.connectedApps.listen((connection) async { + // Ensure that we've established a tab connection before running main. + await tabConnectionCompleter.future; + if (testSettings.autoRun) { + connection.runMain(); + } + + // We may reuse the app connection, so only save it the first time + // it's encountered. + if (!appConnectionCompleter.isCompleted) { + appConnection = connection; + appConnectionCompleter.complete(); + } + }); + + _appUrl = basePath.isEmpty + ? 'http://localhost:$port/$appUrlPath' + : 'http://localhost:$port/$basePath/$appUrlPath'; + + if (testSettings.launchChrome) { + await _webDriver?.get(appUrl).timeout(const Duration(seconds: 30)); + _tabConnection = await _getTabConnection( + connection, + appUrl, + ).timeout(const Duration(seconds: 30)); + tabConnectionCompleter.complete(); + + if (debugSettings.enableDebugExtension) { + final extensionTab = await _fetchDartDebugExtensionTab(connection); + extensionConnection = await extensionTab.connect(); + await extensionConnection.runtime.enable(); + } + + await appConnectionCompleter.future; + if (debugSettings.enableDebugging && !testSettings.waitToDebug) { + await startDebugging(); + } + _webkitDebugger = WebkitDebugger(WipDebugger(tabConnection)); + } else { + // No tab needs to be discovered, so fulfill the relevant completer. + tabConnectionCompleter.complete(); + } + } catch (e, s) { + _logger.severe('Failed to setup the service, $e:$s'); + await tearDown(); + rethrow; + } + } + + /// Creates a VM service connection connected to the debug URI. + /// + /// This can be used to test behavior that should be available to a client + /// connected to DWDS. + Future connectFakeClient() async { + final fakeClient = await vmServiceConnectUri(debugConnection.uri); + + fakeClient.onEvent(EventStreams.kService).listen(_handleServiceEvent); + await fakeClient.streamListen(EventStreams.kService); + + return fakeClient; + } + + /// Returns the service extension method given the [extensionName]. + /// + /// The extension be called by a client created with [connectFakeClient]. + String? getRegisteredServiceExtension(String extensionName) { + if (_serviceNameToMethod.isEmpty) { + throw StateError(''' + No registered service extensions. Did you call connectFakeClient? + '''); + } + + return _serviceNameToMethod[extensionName]; + } + + void _handleServiceEvent(Event e) { + if (e.kind == EventKind.kServiceRegistered) { + final serviceName = e.service!; + _serviceNameToMethod[serviceName] = e.method; + } + } + + Future startDebugging() async { + debugConnection = await testServer.dwds.debugConnection(appConnection); + } + + Future tearDown() async { + await modeTearDown(); + await _webDriver?.quit(closeSession: true); + _chromeDriver?.kill(); + DartUri.currentDirectory = p.current; + await _testServer?.stop(); + _client?.close(); + await _outputDir?.delete(recursive: true); + stopLogWriter(); + await project.tearDown(); + + // clear the state for next setup + _webDriver = null; + _chromeDriver = null; + _testServer = null; + _client = null; + _outputDir = null; + } + + /// Given a list of edits, use file IO to write them to the file system. + /// + /// If `file` has the same name as the project's entry file name, that file + /// will be edited. Otherwise, it's assumed to be a library file. + // TODO(srujzs): It's possible we may want a library file with the same name + // as the entry file, but this function doesn't allow that. Potentially + // support that. + Future makeEdits(List edits) async { + // `dart:io`'s `stat` on Windows does not have millisecond precision so we + // need to make sure we wait long enough that modifications result in a + // timestamp that is guaranteed to be after the previous compile. + // TODO(https://github.com/dart-lang/sdk/issues/51937): Remove once this bug + // is fixed. + if (Platform.isWindows) { + await Future.delayed(const Duration(seconds: 1)); + } + _reloadedSources.clear(); + for (var (:file, :originalString, :newString) in edits) { + if (file == project.dartEntryFileName) { + file = project.dartEntryFilePath; + } else { + file = project.dartLibFilePath(file); + } + final f = File(file); + final fileContents = f.readAsStringSync(); + f.writeAsStringSync(fileContents.replaceAll(originalString, newString)); + + _updateReloadedSources(file); + } + } + + /// Updates the reloaded_sources.json manifest file for a running test. + /// + /// This logic essentially replicates the build system's naming conventions + /// for DDC's generated code. DWDS itself uses the metadata file, but this + /// isn't available for our test fixtures. + /// Rules: + /// - Entrypoints (served): web/main.dart -> main + /// - Entrypoints (nested): test/hello_world/main.dart -> hello_world/main + /// - Library files: lib/path/to/some_file.dart + /// -> packages/`package`/path/to/some_file + void _updateReloadedSources(String absolutePath) { + final relativePath = p.relative( + absolutePath, + from: project.absolutePackageDirectory, + ); + final relativeUrl = p.toUri(relativePath).path; + + String moduleName; + String libUri; + String srcPath; + + if (relativeUrl.startsWith('lib/')) { + final pathInLib = relativeUrl.substring(4); + moduleName = + 'packages/${project.packageName}/${p.withoutExtension(pathInLib)}'; + libUri = 'package:${project.packageName}/$pathInLib'; + srcPath = moduleName; + } else if (absolutePath == project.dartEntryFilePath) { + moduleName = p.withoutExtension(relativeUrl); + libUri = project.dartEntryFilePackageUri.toString(); + + final servePath = '${project.directoryToServe}/'; + if (relativeUrl.startsWith(servePath)) { + // e.g. web/main.dart -> main + srcPath = p.withoutExtension(relativeUrl.substring(servePath.length)); + } else { + // e.g. example/hello_world/main.dart -> example/hello_world/main + srcPath = moduleName; + } + } else { + throw StateError( + "Unhandled file path in test context's reloaded_sources.json: " + " $absolutePath. Only entrypoints and files in 'lib/' are supported.", + ); + } + + _reloadedSources.add({ + 'src': '/$srcPath.ddc.js', + 'module': moduleName, + 'libraries': [libUri], + }); + } + + /// Contains contents of the reloaded_sources.json manifest file. + /// + /// Used by the DDC Library Bundle module system to record changed files for + /// hot restart/reload. + final _reloadedSources = >[]; + + void addLibraryFile({required String libFileName, required String contents}) { + final file = File(project.dartLibFilePath(libFileName)); + // Library folder may not exist yet, so create it. + file.createSync(recursive: true); + file.writeAsStringSync(contents); + _updateReloadedSources(file.path); + } + + /// Wraps a handler to serve the reloaded_sources.json file for + /// reloads/restarts in the DDC Library Bundle module system. + Handler handleReloadedSources(Handler proxy) { + return (request) { + final path = request.url.path; + if (path.endsWith(reloadedSourcesFileName)) { + return shelf.Response.ok(jsonEncode(_reloadedSources)); + } + return proxy(request); + }; + } + + Future recompile({required bool fullRestart}) => throw UnsupportedError( + 'recompile is only supported in Frontend Server mode', + ); + + Future waitForSuccessfulBuild({ + Duration? timeout, + bool propagateToBrowser = false, + bool allowFailure = false, + }) => throw UnsupportedError( + 'waitForSuccessfulBuild is only supported in Build Daemon mode', + ); + + Future _buildDebugExtension() async { + final process = await Process.run('tool/build_extension.sh', [ + 'prod', + ], workingDirectory: absolutePath(pathFromDwds: 'debug_extension')); + print(process.stdout); + } + + Future _getTabConnection( + ChromeConnection connection, + String appUrl, + ) async { + final tab = await connection.getTab( + (t) => t.url == appUrl, + retryFor: const Duration(seconds: 5), + ); + if (tab == null) { + throw StateError( + 'Unable to connect to tab after retrying for 5 seconds.', + ); + } + final tabConnection = await tab.connect().timeout( + const Duration(seconds: 30), + ); + await tabConnection.runtime.enable(); + await tabConnection.debugger.enable(); + return tabConnection; + } + + Future _fetchDartDebugExtensionTab( + ChromeConnection connection, + ) async { + const retries = 5; + for (var i = 0; i < retries; i++) { + if (i > 0) { + await Future.delayed(const Duration(milliseconds: 500)); + } + final extensionTabs = (await connection.getTabs()).where((tab) { + return tab.isChromeExtension; + }); + for (final tab in extensionTabs) { + final tabConnection = await tab.connect(); + final response = await tabConnection.runtime.evaluate( + 'window.isDartDebugExtension', + ); + if (response.value == true) { + return tab; + } + } + } + throw StateError('No extension installed.'); + } + + /// Finds the line number in [scriptRef] matching [breakpointId]. + /// + /// A breakpoint ID is found by looking for a line that ends with a comment + /// of exactly this form: `// Breakpoint: `. + /// + /// Throws if it can't find the matching line. + Future findBreakpointLine( + String breakpointId, + String isolateId, + ScriptRef scriptRef, + ) async { + final script = + await debugConnection.vmService.getObject(isolateId, scriptRef.id!) + as Script; + final lines = LineSplitter.split(script.source!).toList(); + final lineNumber = lines.indexWhere( + (l) => l.endsWith('// Breakpoint: $breakpointId'), + ); + if (lineNumber == -1) { + throw StateError( + 'Unable to find breakpoint in ${scriptRef.uri} with id ' + '$breakpointId', + ); + } + return lineNumber + 1; + } +} + +typedef Edit = ({String file, String originalString, String newString}); + +Future _createDriverWithRetry({ + required Map capabilities, + required Uri uri, + int maxAttempts = 3, + Duration timeout = const Duration(seconds: 30), +}) async { + for (var attempt = 1; attempt <= maxAttempts; attempt++) { + try { + return await createDriver( + spec: WebDriverSpec.JsonWire, + desired: capabilities, + uri: uri, + ).timeout(timeout); + } catch (e) { + if (attempt == maxAttempts) rethrow; + await Future.delayed(Duration(seconds: attempt)); + } + } + throw StateError('Unreachable'); +} + +final _sdkRoot = isolate.Isolate.resolvePackageUriSync( + Uri.parse('package:dwds_test_common/fixtures/context.dart'), +)!.resolve('../../../../'); + +final _chromeDriverName = Platform.isWindows + ? 'chromedriver.exe' + : 'chromedriver'; + +final _chromeExecutableName = Platform.isWindows + ? 'Application\\chrome.exe' + : 'google-chrome'; + +String _resolveExecutable({ + required List environmentKeys, + required String sdkRelativePath, + required String fallbackName, +}) { + for (final env in environmentKeys) { + if (Platform.environment.containsKey(env)) { + return Platform.environment[env]!; + } + } + final sdkPath = _sdkRoot.resolve(sdkRelativePath).toFilePath(); + if (File(sdkPath).existsSync()) { + return sdkPath; + } + return fallbackName; +} + +String _resolveChromeDriverExecutable() => _resolveExecutable( + environmentKeys: const ['CHROMEDRIVER_PATH'], + sdkRelativePath: 'third_party/webdriver/chrome/$_chromeDriverName', + fallbackName: _chromeDriverName, +); + +String _resolveChromeExecutable() { + for (final env in const ['CHROME_EXECUTABLE', 'CHROME_PATH']) { + if (Platform.environment.containsKey(env)) { + return Platform.environment[env]!; + } + } + final sdkPath = _sdkRoot + .resolve('third_party/browsers/chrome/chrome/$_chromeExecutableName') + .toFilePath(); + if (File(sdkPath).existsSync()) { + return sdkPath; + } + if (Platform.isWindows) { + final defaultWindowsPaths = [ + if (Platform.environment.containsKey('PROGRAMFILES')) + p.join( + Platform.environment['PROGRAMFILES']!, + r'Google\Chrome\Application\chrome.exe', + ), + if (Platform.environment.containsKey('PROGRAMFILES(X86)')) + p.join( + Platform.environment['PROGRAMFILES(X86)']!, + r'Google\Chrome\Application\chrome.exe', + ), + if (Platform.environment.containsKey('LOCALAPPDATA')) + p.join( + Platform.environment['LOCALAPPDATA']!, + r'Google\Chrome\Application\chrome.exe', + ), + r'C:\Program Files\Google\Chrome\Application\chrome.exe', + r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe', + ]; + for (final path in defaultWindowsPaths) { + if (File(path).existsSync()) { + return path; + } + } + return 'chrome.exe'; + } + if (Platform.isMacOS) { + const defaultMacPath = + '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'; + if (File(defaultMacPath).existsSync()) { + return defaultMacPath; + } + } + return _chromeExecutableName; +} diff --git a/dwds/test/integration/fixtures/debugger_data.dart b/dwds_test_common/lib/fixtures/debugger_data.dart similarity index 100% rename from dwds/test/integration/fixtures/debugger_data.dart rename to dwds_test_common/lib/fixtures/debugger_data.dart diff --git a/dwds/test/integration/fixtures/fakes.dart b/dwds_test_common/lib/fixtures/fakes.dart similarity index 100% rename from dwds/test/integration/fixtures/fakes.dart rename to dwds_test_common/lib/fixtures/fakes.dart diff --git a/dwds/test/integration/fixtures/main.dart.dill.json b/dwds_test_common/lib/fixtures/main.dart.dill.json similarity index 100% rename from dwds/test/integration/fixtures/main.dart.dill.json rename to dwds_test_common/lib/fixtures/main.dart.dill.json diff --git a/dwds/test/integration/fixtures/main.dart.dill.map b/dwds_test_common/lib/fixtures/main.dart.dill.map similarity index 100% rename from dwds/test/integration/fixtures/main.dart.dill.map rename to dwds_test_common/lib/fixtures/main.dart.dill.map diff --git a/dwds/test/integration/fixtures/project.dart b/dwds_test_common/lib/fixtures/project.dart similarity index 96% rename from dwds/test/integration/fixtures/project.dart rename to dwds_test_common/lib/fixtures/project.dart index 3322800e2a..b2d8b809eb 100644 --- a/dwds/test/integration/fixtures/project.dart +++ b/dwds_test_common/lib/fixtures/project.dart @@ -203,9 +203,9 @@ class TestProject { Directory(newPath).createSync(); copyPathSync(currentPath, newPath); copiedPackageDirectories.add(packageDirectory); - final pubspec = loadYaml( - File(p.join(currentPath, 'pubspec.yaml')).readAsStringSync(), - ) as Map; + final pubspec = + loadYaml(File(p.join(currentPath, 'pubspec.yaml')).readAsStringSync()) + as Map; final dependencies = pubspec['dependencies'] as Map? ?? {}; for (final dependency in dependencies.values) { if (dependency is Map && dependency.containsKey('path')) { @@ -229,14 +229,12 @@ class TestProject { } } - // Clean up the project. - // Called when we need to rebuild sdk and the app from previous test - // configurations. - await Process.run('dart', [ - 'run', - 'build_runner', - 'clean', - ], workingDirectory: newPath); + final buildDir = Directory(p.join(newPath, '.dart_tool', 'build')); + if (buildDir.existsSync()) { + try { + buildDir.deleteSync(recursive: true); + } catch (_) {} + } } Future setUp() async { diff --git a/dwds/test/integration/fixtures/server.dart b/dwds_test_common/lib/fixtures/server.dart similarity index 77% rename from dwds/test/integration/fixtures/server.dart rename to dwds_test_common/lib/fixtures/server.dart index 29c455d7ae..27b696129b 100644 --- a/dwds/test/integration/fixtures/server.dart +++ b/dwds_test_common/lib/fixtures/server.dart @@ -6,7 +6,6 @@ import 'dart:io'; -import 'package:build_daemon/data/build_status.dart' as daemon; import 'package:dwds/asset_reader.dart'; import 'package:dwds/dart_web_debug_service.dart'; import 'package:dwds/data/build_result.dart'; @@ -31,18 +30,11 @@ Handler _interceptFavicon(Handler handler) { class TestServer { final HttpServer _server; - final String target; final Dwds dwds; final Stream buildResults; final AssetReader assetReader; - TestServer._( - this.target, - this._server, - this.dwds, - this.buildResults, - this.assetReader, - ); + TestServer._(this._server, this.dwds, this.buildResults, this.assetReader); String get host => _server.address.host; int get port => _server.port; @@ -58,8 +50,7 @@ class TestServer { required Handler assetHandler, required AssetReader assetReader, required LoadStrategy strategy, - required String target, - required Stream buildResults, + required Stream buildResults, required Future Function() chromeConnection, int? port, HttpServer? httpServer, @@ -68,23 +59,6 @@ class TestServer { pipeline = pipeline.addMiddleware(_interceptFavicon); - final filteredBuildResults = buildResults.asyncMap((results) { - final result = results.results.firstWhere( - (result) => result.target == target, - ); - switch (result.status) { - case daemon.BuildStatus.started: - return BuildResult(status: BuildStatus.started); - case daemon.BuildStatus.failed: - return BuildResult(status: BuildStatus.failed); - case daemon.BuildStatus.succeeded: - return BuildResult(status: BuildStatus.succeeded); - default: - break; - } - throw StateError('Unexpected Daemon build result: $result'); - }); - final toolConfiguration = ToolConfiguration( loadStrategy: strategy, debugSettings: debugSettings, @@ -93,7 +67,7 @@ class TestServer { final dwds = await Dwds.start( assetReader: assetReader, - buildResults: filteredBuildResults, + buildResults: buildResults, chromeConnection: chromeConnection, toolConfiguration: toolConfiguration, ); @@ -114,13 +88,7 @@ class TestServer { }, ); - return TestServer._( - target, - server, - dwds, - filteredBuildResults, - assetReader, - ); + return TestServer._(server, dwds, buildResults, assetReader); } /// [Middleware] that logs all requests, inspired by [logRequests]. diff --git a/dwds/test/integration/fixtures/utilities.dart b/dwds_test_common/lib/fixtures/utilities.dart similarity index 87% rename from dwds/test/integration/fixtures/utilities.dart rename to dwds_test_common/lib/fixtures/utilities.dart index 7ca72445b1..d36d901aee 100644 --- a/dwds/test/integration/fixtures/utilities.dart +++ b/dwds_test_common/lib/fixtures/utilities.dart @@ -4,11 +4,6 @@ // @skip_package_deps_validation -import 'dart:io'; - -import 'package:build_daemon/client.dart'; -import 'package:build_daemon/constants.dart'; -import 'package:build_daemon/data/server_log.dart'; import 'package:dds/devtools_server.dart'; import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/loaders/strategy.dart'; @@ -18,32 +13,6 @@ import 'package:dwds/src/services/expression_compiler.dart'; import 'context.dart'; import 'fakes.dart'; -/// Connects to the `build_runner` daemon. -Future connectClient( - String dartPath, - String workingDirectory, - List options, - void Function(ServerLog) logHandler, -) => BuildDaemonClient.connect(workingDirectory, [ - dartPath, - 'run', - 'build_runner', - 'daemon', - ...options, -], logHandler: logHandler); - -/// Returns the port of the daemon asset server. -int daemonPort(String workingDirectory) { - final portFile = File(_assetServerPortFilePath(workingDirectory)); - if (!portFile.existsSync()) { - throw Exception('Unable to read daemon asset port file.'); - } - return int.parse(portFile.readAsStringSync()); -} - -String _assetServerPortFilePath(String workingDirectory) => - '${daemonWorkspace(workingDirectory)}/.asset_server_port'; - /// Retries a callback function with a delay until the result is the /// [expectedResult] (if provided) or is not null. Future retryFn( @@ -107,7 +76,7 @@ class TestDebugSettings extends DebugSettings { TestContext context, { bool serveFromDds = false, }) : super( - // ignore: deprecated_member_use_from_same_package + // ignore: deprecated_member_use devToolsLauncher: serveFromDds ? null : (hostname) async { @@ -138,11 +107,14 @@ class TestDebugSettings extends DebugSettings { required super.useSseForDebugBackend, required super.useSseForDebugProxy, required super.useSseForInjectedClient, + // ignore: deprecated_member_use required super.spawnDds, + // ignore: deprecated_member_use required super.ddsPort, required super.enableDevToolsLaunch, required super.launchDevToolsInNewWindow, required super.emitDebugEvents, + // ignore: deprecated_member_use required super.devToolsLauncher, required super.expressionCompiler, required super.urlEncoder, @@ -169,15 +141,15 @@ class TestDebugSettings extends DebugSettings { useSseForDebugProxy: useSse ?? useSseForDebugProxy, useSseForDebugBackend: useSse ?? useSseForDebugBackend, useSseForInjectedClient: useSse ?? useSseForInjectedClient, - // ignore: deprecated_member_use_from_same_package + // ignore: deprecated_member_use spawnDds: spawnDds ?? this.spawnDds, - // ignore: deprecated_member_use_from_same_package + // ignore: deprecated_member_use ddsPort: ddsPort ?? this.ddsPort, enableDevToolsLaunch: enableDevToolsLaunch ?? this.enableDevToolsLaunch, launchDevToolsInNewWindow: launchDevToolsInNewWindow ?? this.launchDevToolsInNewWindow, emitDebugEvents: emitDebugEvents ?? this.emitDebugEvents, - // ignore: deprecated_member_use_from_same_package + // ignore: deprecated_member_use devToolsLauncher: devToolsLauncher ?? this.devToolsLauncher, expressionCompiler: expressionCompiler ?? this.expressionCompiler, urlEncoder: urlEncoder ?? this.urlEncoder, @@ -259,7 +231,7 @@ class TestSettings { final bool launchChrome; // Build settings. - final CompilationMode compilationMode; + final ModuleFormat moduleFormat; final bool canaryFeatures; final bool isFlutterApp; @@ -273,7 +245,7 @@ class TestSettings { this.enableExpressionEvaluation = false, this.verboseCompiler = false, this.launchChrome = true, - this.compilationMode = CompilationMode.buildDaemon, + this.moduleFormat = ModuleFormat.amd, this.canaryFeatures = false, this.isFlutterApp = false, diff --git a/dwds_test_common/lib/frontend_server_common/CHANGELOG-legacy.md b/dwds_test_common/lib/frontend_server_common/CHANGELOG-legacy.md new file mode 100644 index 0000000000..b05b83a9f3 --- /dev/null +++ b/dwds_test_common/lib/frontend_server_common/CHANGELOG-legacy.md @@ -0,0 +1,26 @@ +## 0.2.3-wip + +- Update Dart SDK constraint to `^3.10.0`. +- Add bootstrapping code for DDC library bundle format. +- Added scriptUri to compileExpression*Request +- Adding `createReloadedSourceEntry` for sharing reloaded_sources.json entry logic. + +## 0.2.2 + +- Start the frontend server from the AOT snapshot shipped in the Dart SDK. + +## 0.2.1 + +- Doe not pass `-debugger-module-names` flag to the frontend server. + +## 0.2.0 + +- Migrate to null safety + +## 0.1.1 + +- Remove dead code + +## 0.1.0 + +- Initial version diff --git a/dwds_test_common/lib/frontend_server_common/README.md b/dwds_test_common/lib/frontend_server_common/README.md new file mode 100644 index 0000000000..61862a5af1 --- /dev/null +++ b/dwds_test_common/lib/frontend_server_common/README.md @@ -0,0 +1,14 @@ +Dart Web Developer Service + +__*Note: Under heavy development.*__ + +This code is an edited copy of flutter code used for setting up frontend server +and components that are needed to communicate to Chrome and dwds: + +- frontend server client +- web runner +- dev fs +- asset server + +This eventually will transform into common code that both flutter and dwds use +for better integration. diff --git a/dwds_test_common/lib/frontend_server_common/asset_server.dart b/dwds_test_common/lib/frontend_server_common/asset_server.dart new file mode 100644 index 0000000000..ef39ff0b35 --- /dev/null +++ b/dwds_test_common/lib/frontend_server_common/asset_server.dart @@ -0,0 +1,363 @@ +// Copyright 2020 The Dart Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Note: this is a copy from flutter tools, updated to work with dwds tests + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:dwds/asset_reader.dart'; +import 'package:dwds/config.dart'; +import 'package:dwds_test_common/test_sdk_layout.dart'; +import 'package:file/file.dart'; +import 'package:logging/logging.dart'; +import 'package:mime/mime.dart' as mime; +import 'package:shelf/shelf.dart' as shelf; + +class TestAssetServer implements AssetReader { + late final String _basePath; + final String index; + + final _logger = Logger('TestAssetServer'); + + // Fallback to "application/octet-stream" on null which + // makes no claims as to the structure of the data. + static const String _defaultMimeType = 'application/octet-stream'; + final Uri _projectDirectory; + final FileSystem _fileSystem; + final HttpServer _httpServer; + final Map _files = {}; + final Map _sourceMaps = {}; + final Map _metadata = {}; + late String _mergedMetadata; + final PackageUriMapper _packageUriMapper; + final InternetAddress internetAddress; + final TestSdkLayout _sdkLayout; + + TestAssetServer( + this.index, + this._httpServer, + this._packageUriMapper, + this.internetAddress, + this._projectDirectory, + this._fileSystem, + this._sdkLayout, + ) { + _basePath = _parseBasePathFromIndexHtml(index); + } + + @override + String get basePath => _basePath; + + bool hasFile(String path) => _files.containsKey(path); + Uint8List getFile(String path) => _files[path]!; + + bool hasSourceMap(String path) => _sourceMaps.containsKey(path); + Uint8List getSourceMap(String path) => _sourceMaps[path]!; + + bool hasMetadata(String path) => _metadata.containsKey(path); + Uint8List getMetadata(String path) => _metadata[path]!; + + /// Start the web asset server on a [hostname] and [port]. + /// + /// Unhandled exceptions will throw a exception with the error and stack + /// trace. + static Future start( + String sdkDirectory, + Uri projectDirectory, + FileSystem fileSystem, + String index, + String hostname, + int port, + UrlEncoder? urlTunneler, + PackageUriMapper packageUriMapper, + ) async { + final address = (await InternetAddress.lookup(hostname)).first; + final httpServer = await HttpServer.bind(address, port); + final sdkLayout = TestSdkLayout.createDefault(sdkDirectory); + final server = TestAssetServer( + index, + httpServer, + packageUriMapper, + address, + projectDirectory, + fileSystem, + sdkLayout, + ); + return server; + } + + // handle requests for JavaScript source, dart sources maps, or asset files. + Future handleRequest(shelf.Request request) async { + if (request.method != 'GET') { + // Assets are served via GET only. + return shelf.Response.notFound(''); + } + final requestPath = _stripBasePath(request.url.path, basePath); + if (requestPath == null) { + return shelf.Response.notFound(''); + } + + final headers = {}; + + if (request.url.path.endsWith('.html')) { + final indexFile = _fileSystem.file(_projectDirectory.resolve(index)); + if (indexFile.existsSync()) { + headers[HttpHeaders.contentTypeHeader] = 'text/html'; + headers[HttpHeaders.contentLengthHeader] = indexFile + .lengthSync() + .toString(); + return shelf.Response.ok(indexFile.openRead(), headers: headers); + } + return shelf.Response.notFound(''); + } + + // If this is a JavaScript file, it must be in the in-memory cache. + // Attempt to look up the file by URI. + if (hasFile(requestPath)) { + final List bytes = getFile(requestPath); + headers[HttpHeaders.contentLengthHeader] = bytes.length.toString(); + headers[HttpHeaders.contentTypeHeader] = 'application/javascript'; + return shelf.Response.ok(bytes, headers: headers); + } + // If this is a sourcemap file, then it might be in the in-memory cache. + // Attempt to lookup the file by URI. + if (hasSourceMap(requestPath)) { + final List bytes = getSourceMap(requestPath); + headers[HttpHeaders.contentLengthHeader] = bytes.length.toString(); + headers[HttpHeaders.contentTypeHeader] = 'application/json'; + return shelf.Response.ok(bytes, headers: headers); + } + // If this is a metadata file, then it might be in the in-memory cache. + // Attempt to lookup the file by URI. + if (hasMetadata(requestPath)) { + final List bytes = getMetadata(requestPath); + headers[HttpHeaders.contentLengthHeader] = bytes.length.toString(); + headers[HttpHeaders.contentTypeHeader] = 'application/json'; + return shelf.Response.ok(bytes, headers: headers); + } + + final file = _resolveDartFile(requestPath); + if (!file.existsSync()) { + return shelf.Response.notFound(''); + } + + final length = file.lengthSync(); + // Attempt to determine the file's mime type. if this is not provided some + // browsers will refuse to render images/show video et cetera. If the tool + // cannot determine a mime type, fall back to application/octet-stream. + String? mimeType; + if (length >= 12) { + mimeType = mime.lookupMimeType( + file.path, + headerBytes: await file.openRead(0, 12).first, + ); + } + mimeType ??= _defaultMimeType; + headers[HttpHeaders.contentLengthHeader] = length.toString(); + headers[HttpHeaders.contentTypeHeader] = mimeType; + return shelf.Response.ok(file.openRead(), headers: headers); + } + + /// Tear down the http server running. + @override + Future close() { + return _httpServer.close(); + } + + /// Write a single file into the in-memory cache. + void writeFile(String filePath, String contents) { + _files[filePath] = Uint8List.fromList(utf8.encode(contents)); + } + + /// Update the in-memory asset server with the provided source and manifest + /// files. + /// + /// Returns a list of updated modules. + List write( + File codeFile, + File manifestFile, + File sourcemapFile, + File metadataFile, + ) { + final modules = []; + final codeBytes = codeFile.readAsBytesSync(); + final sourcemapBytes = sourcemapFile.readAsBytesSync(); + final metadataBytes = metadataFile.readAsBytesSync(); + final manifest = _castStringKeyedMap( + json.decode(manifestFile.readAsStringSync()), + ); + for (final filePath in manifest.keys) { + final offsets = _castStringKeyedMap(manifest[filePath]); + final codeOffsets = (offsets['code'] as List).cast(); + final sourcemapOffsets = (offsets['sourcemap'] as List) + .cast(); + final metadataOffsets = (offsets['metadata'] as List) + .cast(); + if (codeOffsets.length != 2 || + sourcemapOffsets.length != 2 || + metadataOffsets.length != 2) { + _logger.severe('Invalid manifest byte offsets: $offsets'); + continue; + } + + final codeStart = codeOffsets[0]; + final codeEnd = codeOffsets[1]; + if (codeStart < 0 || codeEnd > codeBytes.lengthInBytes) { + _logger.severe('Invalid byte index: [$codeStart, $codeEnd]'); + continue; + } + final byteView = Uint8List.view( + codeBytes.buffer, + codeStart, + codeEnd - codeStart, + ); + + final fileName = filePath.startsWith('/') + ? filePath.substring(1) + : filePath; + _files[fileName] = byteView; + + final sourcemapStart = sourcemapOffsets[0]; + final sourcemapEnd = sourcemapOffsets[1]; + if (sourcemapStart < 0 || sourcemapEnd > sourcemapBytes.lengthInBytes) { + _logger.severe('Invalid byte index: [$sourcemapStart, $sourcemapEnd]'); + continue; + } + final sourcemapView = Uint8List.view( + sourcemapBytes.buffer, + sourcemapStart, + sourcemapEnd - sourcemapStart, + ); + _sourceMaps['$fileName.map'] = sourcemapView; + + final metadataStart = metadataOffsets[0]; + final metadataEnd = metadataOffsets[1]; + if (metadataStart < 0 || metadataEnd > metadataBytes.lengthInBytes) { + _logger.severe('Invalid byte index: [$metadataStart, $metadataEnd]'); + continue; + } + final metadataView = Uint8List.view( + metadataBytes.buffer, + metadataStart, + metadataEnd - metadataStart, + ); + _metadata['$fileName.metadata'] = metadataView; + + modules.add(fileName); + } + + _mergedMetadata = _metadata.values + .map((Uint8List encoded) => utf8.decode(encoded)) + .join('\n'); + + return modules; + } + + // Attempt to resolve `path` to a dart file. + File _resolveDartFile(String path) { + // If this is a dart file, it must be on the local file system and is + // likely coming from a source map request. The tool doesn't currently + // consider the case of Dart files as assets. + final dartFile = _fileSystem.file(_projectDirectory.resolve(path)); + if (dartFile.existsSync()) { + return dartFile; + } + + final segments = path.split('/'); + + // The file might have been a package file which is signaled by a + // `/packages//` request. + if (segments.first == 'packages') { + var resolved = _packageUriMapper.serverPathToResolvedUri(path); + if (resolved != null) { + resolved = _projectDirectory.resolveUri(resolved); + } + final packageFile = _fileSystem.file(resolved); + if (packageFile.existsSync()) { + return packageFile; + } + _logger.severe('Package file not found: $path ($packageFile)'); + } + + // Otherwise it must be a Dart SDK source. + final dartSdkParent = _fileSystem.directory(_sdkLayout.sdkDirectory).parent; + final dartSdkFile = _fileSystem.file( + _fileSystem.path.joinAll([dartSdkParent.path, ...segments]), + ); + return dartSdkFile; + } + + @override + Future dartSourceContents(String serverPath) async { + final stripped = _stripBasePath(serverPath, basePath); + if (stripped != null) { + final result = _resolveDartFile(stripped); + if (result.existsSync()) { + return result.readAsString(); + } + } + _logger.severe('Source not found: $serverPath'); + return null; + } + + @override + Future sourceMapContents(String serverPath) async { + final stripped = _stripBasePath(serverPath, basePath); + if (stripped != null) { + if (hasSourceMap(stripped)) { + return utf8.decode(getSourceMap(stripped)); + } + } + _logger.severe('Source map not found: $serverPath'); + return null; + } + + @override + Future metadataContents(String serverPath) async { + final stripped = _stripBasePath(serverPath, basePath); + if (stripped != null) { + if (stripped.endsWith('.ddc_merged_metadata')) { + return _mergedMetadata; + } + if (hasMetadata(stripped)) { + return utf8.decode(getMetadata(stripped)); + } + } + _logger.severe('Metadata not found: $serverPath'); + return null; + } + + String _parseBasePathFromIndexHtml(String index) { + final file = _fileSystem.file(_projectDirectory.resolve(index)); + if (!file.existsSync()) { + throw StateError('Index file $index is not found'); + } + final contents = file.readAsStringSync(); + final matches = RegExp(r'').allMatches(contents); + if (matches.isEmpty) return ''; + return matches.first.group(1) ?? ''; + } + + String? _stripBasePath(String path, String basePath) { + path = stripLeadingSlashes(path); + if (path.startsWith(basePath)) { + path = path.substring(basePath.length); + } else { + // The given path isn't under base path, return null to indicate that. + _logger.severe('Path is not under $basePath: $path'); + return null; + } + return stripLeadingSlashes(path); + } +} + +/// Given a data structure which is a Map of String to dynamic values, return +/// the same structure (`Map`) with the correct runtime types. +Map _castStringKeyedMap(dynamic untyped) { + final map = untyped as Map; + return map.cast(); +} diff --git a/dwds_test_common/lib/frontend_server_common/bootstrap.dart b/dwds_test_common/lib/frontend_server_common/bootstrap.dart new file mode 100644 index 0000000000..8efe76ec57 --- /dev/null +++ b/dwds_test_common/lib/frontend_server_common/bootstrap.dart @@ -0,0 +1,573 @@ +// Copyright 2020 The Dart Authors. 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:io' show Platform; + +// Note: this is a copy from flutter tools, updated to work with dwds tests + +/// JavaScript snippet to determine the base URL of the current path. +const String _baseUrlScript = ''' +var baseUrl = (function () { + // Attempt to detect --precompiled mode for tests, and set the base url + // appropriately, otherwise set it to '/'. + var pathParts = location.pathname.split("/"); + if (pathParts[0] == "") { + pathParts.shift(); + } + if (pathParts.length > 1 && pathParts[1] == "test") { + return "/" + pathParts.slice(0, 2).join("/") + "/"; + } + // Attempt to detect base url using html tag + // base href should start and end with "/" + if (typeof document !== 'undefined') { + var el = document.getElementsByTagName('base'); + if (el && el[0] && el[0].getAttribute("href") && el[0].getAttribute + ("href").startsWith("/") && el[0].getAttribute("href").endsWith("/")){ + return el[0].getAttribute("href"); + } + } + // return default value + return "/"; +}()); +var _trimmedBaseUrl = baseUrl.endsWith('/') ? baseUrl.substring(0, baseUrl.length - 1) : baseUrl; +var _currentDirectory = window.location.origin + _trimmedBaseUrl; +'''; + +/// Used to load prerequisite scripts such as ddc_module_loader.js +const String _simpleLoaderScript = r''' +window.$dartCreateScript = (function() { + // Find the nonce value. (Note, this is only computed once.) + var scripts = Array.from(document.getElementsByTagName("script")); + var nonce; + scripts.some( + script => (nonce = script.nonce || script.getAttribute("nonce"))); + // If present, return a closure that automatically appends the nonce. + if (nonce) { + return function() { + var script = document.createElement("script"); + script.nonce = nonce; + return script; + }; + } else { + return function() { + return document.createElement("script"); + }; + } +})(); + +// Loads a module [relativeUrl] relative to [root]. +// +// If not specified, [root] defaults to the directory serving the main app. +var forceLoadModule = function (relativeUrl, root) { + var actualRoot = root ?? _currentDirectory; + var trimmedRoot = actualRoot.endsWith('/') ? actualRoot.substring(0, actualRoot.length - 1) : actualRoot; + return new Promise(function(resolve, reject) { + var script = self.$dartCreateScript(); + let policy = { + createScriptURL: function(src) {return src;} + }; + if (self.trustedTypes && self.trustedTypes.createPolicy) { + policy = self.trustedTypes.createPolicy('dartDdcModuleUrl', policy); + } + script.onload = resolve; + script.onerror = reject; + script.src = policy.createScriptURL(trimmedRoot + "/" + relativeUrl); + document.head.appendChild(script); + }); +}; +'''; + +/// The JavaScript bootstrap script to support in-browser hot restart. +/// +/// The [requireUrl] loads our cached RequireJS script file. The [mapperUrl] +/// loads the special Dart stack trace mapper. The [entrypoint] is the +/// actual main.dart file. +/// +/// This file is served when the browser requests "main.dart.js" in debug mode, +/// and is responsible for bootstrapping the RequireJS modules and attaching +/// the hot reload hooks. +String generateBootstrapScript({ + required String requireUrl, + required String mapperUrl, + required String entrypoint, +}) { + return ''' +"use strict"; + +// Attach source mapping. +var mapperEl = document.createElement("script"); +mapperEl.defer = true; +mapperEl.async = false; +mapperEl.src = "$mapperUrl"; +document.head.appendChild(mapperEl); + +// Attach require JS. +var requireEl = document.createElement("script"); +requireEl.defer = true; +requireEl.async = false; +requireEl.src = "$requireUrl"; +// This attribute tells require JS what to load as main (defined below). +requireEl.setAttribute("data-main", "main_module.bootstrap"); +document.head.appendChild(requireEl); +'''; +} + +/// Generate a synthetic main module which captures the application's main +/// method. +/// +/// RE: Object.keys usage in app.main: +/// This attaches the main entrypoint and hot reload functionality to the +/// window. The app module will have a single property which contains the +/// actual application code. The property name is based off of the entrypoint +/// that is generated, for example the file `foo/bar/baz.dart` will generate a +/// property named approximately `foo__bar__baz`. Rather than attempt to guess, +/// we assume the first property of this object is the module. +String generateMainModule({required String entrypoint}) { + return '''/* ENTRYPOINT_EXTENTION_MARKER */ + +// Create the main module loaded below. +define("main_module.bootstrap", ["$entrypoint", "dart_sdk"], function(app, dart_sdk) { + dart_sdk._isolate_helper.startRootIsolate(() => {}, []); + dart_sdk._debugger.registerDevtoolsFormatter(); + let voidToNull = () => (voidToNull = dart_sdk.dart.constFn(dart_sdk.dart.fnType(dart_sdk.core.Null, [dart_sdk.dart.void])))(); + + // See the generateMainModule doc comment. + var child = {}; + child.main = app[Object.keys(app)[0]].main; + + /* MAIN_EXTENSION_MARKER */ + child.main(); +}); +'''; +} + +String generateDDCBootstrapScript({ + required String ddcModuleLoaderUrl, + required String mapperUrl, + required String entrypoint, + required String bootstrapUrl, +}) { + return ''' +$_baseUrlScript +$_simpleLoaderScript + +(function() { + let appName = "$entrypoint"; + + // A uuid that identifies a subapp. + let uuid = "00000000-0000-0000-0000-000000000000"; + + window.postMessage( + {type: "DDC_STATE_CHANGE", state: "initial_load", targetUuid: uuid}, "*"); + + // Load pre-requisite DDC scripts. We intentionally use invalid names to avoid namespace clashes. + let prerequisiteScripts = [ + { + "src": "$ddcModuleLoaderUrl", + "id": "dart_library \x00" + }, + { + "src": "$mapperUrl", + "id": "dart_stack_trace_mapper \x00" + } + ]; + + // Load ddc_module_loader.js to access DDC's module loader API. + let prerequisiteLoads = []; + for (let i = 0; i < prerequisiteScripts.length; i++) { + prerequisiteLoads.push(forceLoadModule(prerequisiteScripts[i].src)); + } + Promise.all(prerequisiteLoads).then((_) => afterPrerequisiteLogic()); + + // Save the current script so we can access it in a closure. + var _currentScript = document.currentScript; + + var afterPrerequisiteLogic = function() { + window.\$dartLoader.rootDirectories.push(_currentDirectory); + let scripts = [ + { + "src": "dart_sdk.js", + "id": "dart_sdk" + }, + { + "src": "$bootstrapUrl", + "id": "data-main" + } + ]; + let loadConfig = new window.\$dartLoader.LoadConfiguration(); + loadConfig.root = _currentDirectory; + loadConfig.bootstrapScript = scripts[scripts.length - 1]; + + if (window.\$dartJITModules) { + loadConfig.loadScriptFn = function(loader) { + // Loads just the entrypoint module and required SDK modules. + let moduleSet = new Set(); + // This cache is populated by ddc_module_loader.js + let libraryCache = JSON.parse(window.localStorage.getItem(`dartLibraryCache:\${appName}`)); + if (libraryCache) { + // TODO(b/165021238) - when should this be invalidated? + moduleSet = new Set(libraryCache["modules"]) + } + loader.addScriptsToQueue(scripts, function(script) { + // Preemptively load the ddc module loader and previously executed modules. + return moduleSet.size == 0 + || script.id.includes("dart_library") + // We preemptively load the stack_trace_mapper module so that we can + // translate JS errors to Dart. + || script.id.includes("stack_trace_mapper") + || moduleSet.has(script.id); + }); + loader.loadEnqueuedModules(); + } + loadConfig.ddcEventForLoadStart = /* LOAD_ENTRYPOINT_MODULES_START */ 4; + loadConfig.ddcEventForLoadedOk = /* LOAD_ENTRYPOINT_MODULES_END_OK */ 5; + loadConfig.ddcEventForLoadedError = /* LOAD_ENTRYPOINT_MODULES_END_ERROR */ 6; + } else { + loadConfig.loadScriptFn = function(loader) { + loader.addScriptsToQueue(scripts, null); + loader.loadEnqueuedModules(); + } + loadConfig.ddcEventForLoadStart = /* LOAD_ALL_MODULES_START */ 1; + loadConfig.ddcEventForLoadedOk = /* LOAD_ALL_MODULES_END_OK */ 2; + loadConfig.ddcEventForLoadedError = /* LOAD_ALL_MODULES_END_ERROR */ 3; + } + + let loader = new window.\$dartLoader.DDCLoader(loadConfig); + + // Record prerequisite scripts' fully resolved URLs. + prerequisiteScripts.forEach(script => loader.registerScript(script)); + + // Note: these variables should only be used in non-multi-app scenarios since + // they can be arbitrarily overridden based on multi-app load order. + window.\$dartLoader.loadConfig = loadConfig; + window.\$dartLoader.loader = loader; + loader.nextAttempt(); + + let currentUri = _currentScript.src; + let fetchEtagsUri; + if (currentUri.indexOf("?") == -1) { + fetchEtagsUri = currentUri + "?fetch-etags=true"; + } else { + fetchEtagsUri = currentUri + "&fetch-etags=true"; + } + + if (!window.\$dartAppNameToMetadata) { + window.\$dartAppNameToMetadata = new Map(); + } + window.\$dartAppNameToMetadata.set(appName, { + currentDirectory: _currentDirectory, + currentUri: currentUri, + fetchEtagsUri: fetchEtagsUri, + }); + + if (!window.\$dartReloadModifiedModules) { + window.\$dartReloadModifiedModules = (function(appName, callback) { + function cb() { + window.postMessage( + { + type: "DDC_STATE_CHANGE", + state: "restart_end", + targetUuid: uuid, + }, + "*"); + callback(); + } + window.postMessage( + { + type: "DDC_STATE_CHANGE", + state: "restart_begin", + targetUuid: uuid, + }, + "*"); + var xhttp = new XMLHttpRequest(); + xhttp.withCredentials = true; + xhttp.onreadystatechange = function() { + // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState + if (this.readyState == 4 && this.status == 200 || this.status == 304) { + var scripts = JSON.parse(this.responseText); + var numToLoad = 0; + var numLoaded = 0; + for (var i = 0; i < scripts.length; i++) { + var script = scripts[i]; + if (script.id == null) continue; + var src = + window.\$dartAppNameToMetadata.get(appName).currentDirectory + + script.src.toString(); + var oldSrc = window.\$dartLoader.moduleIdToUrl.get(script.id); + // Only compare the search parameters which contain the cache + // busting portion of the uri. The path might be different if the + // script is loaded from a different application on the page. + if (new URL(oldSrc).search == new URL(src).search) continue; + + // We might actually load from a different uri, delete the old one + // just to be sure. + window.\$dartLoader.urlToModuleId.delete(oldSrc); + + window.\$dartLoader.moduleIdToUrl.set(script.id, src); + window.\$dartLoader.urlToModuleId.set(src, script.id); + + if (window.\$dartJITModules) { + // Simply invalidate the import and the corresponding module will + // be lazily loaded. + dart_library.invalidateImport(script.id); + continue; + } else { + numToLoad++; + } + + var el = document.getElementById(script.id); + if (el) el.remove(); + el = window.\$dartCreateScript(); + el.src = policy.createScriptURL(src); + el.async = false; + el.defer = true; + el.id = script.id; + el.onload = function() { + numLoaded++; + if (numToLoad == numLoaded) cb(); + }; + document.head.appendChild(el); + } + // Call `cb` right away if we found no updated scripts. + if (numToLoad == 0) cb(); + } + }; + xhttp.open("GET", + window.\$dartAppNameToMetadata.get(appName).fetchEtagsUri, true); + let sdk = dart_library.import("dart_sdk", appName); + let developer = sdk.developer; + if (developer._extensions.containsKey("ext.flutter.disassemble")) { + developer.invokeExtension("ext.flutter.disassemble", "{}").then(() => { + // TODO(b/204210914): we should really be clearing all statics for all + // apps, but for now we just do it for flutter apps which we recognize + // based on this extension. + sdk.dart.hotRestart(); + xhttp.send(); + }); + } else { + xhttp.send(); + } + }); + } + } +})(); +'''; +} + +String generateDDCMainModule({ + required String entrypoint, + String? exportedMain, +}) { + final exportedMainName = exportedMain ?? entrypoint.split('.')[0]; + return '''/* ENTRYPOINT_EXTENTION_MARKER */ + +(function() { + let appName = "$entrypoint"; + + // A uuid that identifies a subapp. + let uuid = "00000000-0000-0000-0000-000000000000"; + + let dart_sdk = dart_library.import('dart_sdk', appName); + + dart_sdk._debugger.registerDevtoolsFormatter(); + dart_sdk._isolate_helper.startRootIsolate(() => {}, []); + + let child = {}; + child.main = function() { + dart_library.start(appName, uuid, "$entrypoint", "$exportedMainName"); + } + + /* MAIN_EXTENSION_MARKER */ + child.main(); +})(); +'''; +} + +String generateDDCLibraryBundleBootstrapScript({ + required String ddcModuleLoaderUrl, + required String mapperUrl, + required String entrypoint, + required String bootstrapUrl, +}) { + return ''' +$_baseUrlScript +$_simpleLoaderScript + +(function() { + let appName = "org-dartlang-app:/$entrypoint"; + + // Load pre-requisite DDC scripts. We intentionally use invalid names to avoid + // namespace clashes. + let prerequisiteScripts = [ + { + "src": "$ddcModuleLoaderUrl", + "id": "ddc_module_loader \x00" + }, + { + "src": "$mapperUrl", + "id": "dart_stack_trace_mapper \x00" + } + ]; + + // Load ddc_module_loader.js to access DDC's module loader API. + let prerequisiteLoads = []; + for (let i = 0; i < prerequisiteScripts.length; i++) { + prerequisiteLoads.push(forceLoadModule(prerequisiteScripts[i].src)); + } + Promise.all(prerequisiteLoads).then((_) => afterPrerequisiteLogic()); + + // Save the current script so we can access it in a closure. + var _currentScript = document.currentScript; + + // Create a policy if needed to load the files during a hot restart. + let policy = { + createScriptURL: function(src) {return src;} + }; + if (self.trustedTypes && self.trustedTypes.createPolicy) { + policy = self.trustedTypes.createPolicy('dartDdcModuleUrl', policy); + } + + var afterPrerequisiteLogic = function() { + window.\$dartLoader.rootDirectories.push(_currentDirectory); + let scripts = [ + { + "src": "dart_sdk.js", + "id": "dart_sdk" + }, + { + "src": "$bootstrapUrl", + "id": "data-main" + } + ]; + + let loadConfig = new window.\$dartLoader.LoadConfiguration(); + loadConfig.root = _currentDirectory; + + // TODO(srujzs): Verify this is sufficient for Windows. + loadConfig.isWindows = ${Platform.isWindows}; + loadConfig.bootstrapScript = scripts[scripts.length - 1]; + + loadConfig.loadScriptFn = function(loader) { + loader.addScriptsToQueue(scripts, null); + loader.loadEnqueuedModules(); + } + loadConfig.ddcEventForLoadStart = /* LOAD_ALL_MODULES_START */ 1; + loadConfig.ddcEventForLoadedOk = /* LOAD_ALL_MODULES_END_OK */ 2; + loadConfig.ddcEventForLoadedError = /* LOAD_ALL_MODULES_END_ERROR */ 3; + + let loader = new window.\$dartLoader.DDCLoader(loadConfig); + + // Record prerequisite scripts' fully resolved URLs. + prerequisiteScripts.forEach(script => loader.registerScript(script)); + + // Note: these variables should only be used in non-multi-app scenarios + // since they can be arbitrarily overridden based on multi-app load order. + window.\$dartLoader.loadConfig = loadConfig; + window.\$dartLoader.loader = loader; + + // Begin loading libraries + loader.nextAttempt(); + + // Set up stack trace mapper. + if (window.\$dartStackTraceUtility && + !window.\$dartStackTraceUtility.ready) { + window.\$dartStackTraceUtility.ready = true; + window.\$dartStackTraceUtility.setSourceMapProvider(function(url) { + var baseUrl = window.location.protocol + '//' + window.location.host; + url = url.replace(baseUrl + '/', ''); + if (url == 'dart_sdk.js') { + return dartDevEmbedder.debugger.getSourceMap('dart_sdk'); + } + url = url.replace(".lib.js", "").replace(".ddc.js", ""); + return dartDevEmbedder.debugger.getSourceMap(url); + }); + } + + if (!window.\$dartReloadModifiedModules) { + window.\$dartReloadModifiedModules = (function(filesToReload, appName) { + return new Promise(function(resolve) { + function callback() { + resolve(filesToReload); + } + let numToLoad = 0; + let numLoaded = 0; + for (let i = 0; i < filesToReload.length; i++) { + const file = filesToReload[i]; + const module = file.module; + if (module == null) continue; + const src = file.src; + const oldSrc = window.\$dartLoader.moduleIdToUrl.get(module); + + // We might actually load from a different uri, delete the old one + // just to be sure. + window.\$dartLoader.urlToModuleId.delete(oldSrc); + + window.\$dartLoader.moduleIdToUrl.set(module, src); + window.\$dartLoader.urlToModuleId.set(src, module); + + numToLoad++; + + let el = document.getElementById(module); + if (el) el.remove(); + el = window.\$dartCreateScript(); + el.src = policy.createScriptURL(src); + el.async = false; + el.defer = true; + el.id = module; + el.onload = function() { + numLoaded++; + if (numToLoad == numLoaded) callback(); + }; + document.head.appendChild(el); + } + // Call `callback` right away if we found no updated scripts. + if (numToLoad == 0) callback(); + }); + }); + } + }; +})(); +'''; +} + +const String _onLoadEndCallback = r'$onLoadEndCallback'; + +String generateDDCLibraryBundleMainModule({ + required String entrypoint, + required String onLoadEndBootstrap, +}) { + // The typo below in "EXTENTION" is load-bearing, package:build depends on it. + return ''' +/* ENTRYPOINT_EXTENTION_MARKER */ + +(function() { + let appName = "org-dartlang-app:///$entrypoint"; + + dartDevEmbedder.debugger.registerDevtoolsFormatter(); + + // Set up a final script that lets us know when all scripts have been loaded. + // Only then can we call the main method. + let onLoadEndSrc = '$onLoadEndBootstrap'; + window.\$dartLoader.loadConfig.bootstrapScript = { + src: onLoadEndSrc, + id: onLoadEndSrc, + }; + window.\$dartLoader.loadConfig.tryLoadBootstrapScript = true; + // Should be called by $onLoadEndBootstrap once all the scripts have been + // loaded. + window.$_onLoadEndCallback = function() { + let child = {}; + child.main = function() { + dartDevEmbedder.runMain(appName, {}); + } + /* MAIN_EXTENSION_MARKER */ + child.main(); + } +})(); +'''; +} + +String generateDDCLibraryBundleOnLoadEndBootstrap() { + return '''window.$_onLoadEndCallback();'''; +} diff --git a/dwds_test_common/lib/frontend_server_common/devfs.dart b/dwds_test_common/lib/frontend_server_common/devfs.dart new file mode 100644 index 0000000000..a7800f38a1 --- /dev/null +++ b/dwds_test_common/lib/frontend_server_common/devfs.dart @@ -0,0 +1,395 @@ +// Copyright 2020 The Dart Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Note: this is a copy from flutter tools, updated to work with dwds tests + +import 'dart:convert'; +import 'dart:io'; + +import 'package:dwds/asset_reader.dart'; +import 'package:dwds/config.dart'; +import 'package:dwds/expression_compiler.dart'; +// ignore: implementation_imports +import 'package:dwds/src/debugging/metadata/module_metadata.dart'; +import 'package:dwds/utilities.dart'; +import 'package:dwds_test_common/test_sdk_layout.dart'; +import 'package:file/file.dart'; +import 'package:path/path.dart' as p; + +import 'asset_server.dart'; +import 'bootstrap.dart'; +import 'frontend_server_client.dart'; + +class WebDevFS { + WebDevFS({ + required this.fileSystem, + required this.hostname, + required this.port, + required this.projectDirectory, + required this.packageUriMapper, + required this.index, + this.urlTunneler, + required this.sdkLayout, + required this.compilerOptions, + }); + + final FileSystem fileSystem; + late final TestAssetServer assetServer; + final String hostname; + final int port; + final Uri projectDirectory; + final PackageUriMapper packageUriMapper; + final String index; + final UrlEncoder? urlTunneler; + List sources = []; + DateTime? lastCompiled; + + final TestSdkLayout sdkLayout; + final CompilerOptions compilerOptions; + + Future create() async { + assetServer = await TestAssetServer.start( + sdkLayout.sdkDirectory, + projectDirectory, + fileSystem, + index, + hostname, + port, + urlTunneler, + packageUriMapper, + ); + return Uri.parse('http://$hostname:$port'); + } + + Future dispose() { + return assetServer.close(); + } + + Future update({ + required Uri mainUri, + required String dillOutputPath, + required ResidentCompiler generator, + required List invalidatedFiles, + required bool initialCompile, + required bool fullRestart, + // The uri of the `HttpServer` that handles file requests. + // TODO(srujzs): This should be the same as the uri of the AssetServer to + // align with Flutter tools, but currently is not. Delete when that's fixed. + required Uri? fileServerUri, + }) async { + final mainPath = mainUri.toFilePath(); + final outputDirectory = fileSystem.directory( + fileSystem.file(projectDirectory.resolve(mainPath)).parent.path, + ); + final entryPoint = mainUri.toString(); + + var prefix = ''; + // If base path is not overwritten, use main's subdirectory + // to store all files, so the paths match the requests. + if (assetServer.basePath.isEmpty) { + final directory = p.dirname(entryPoint); + prefix = '$directory/'; + } + + if (initialCompile) { + final ddcModuleLoader = '${prefix}ddc_module_loader.js'; + final require = '${prefix}require.js'; + final stackMapper = '${prefix}stack_trace_mapper.js'; + final main = '${prefix}main.dart.js'; + final bootstrap = '${prefix}main_module.bootstrap.js'; + + assetServer.writeFile( + entryPoint, + fileSystem.file(projectDirectory.resolve(mainPath)).readAsStringSync(), + ); + assetServer.writeFile(stackMapper, stackTraceMapper.readAsStringSync()); + + switch (ddcModuleFormat) { + case ModuleFormat.amd: + assetServer.writeFile(require, requireJS.readAsStringSync()); + assetServer.writeFile( + main, + generateBootstrapScript( + requireUrl: 'require.js', + mapperUrl: 'stack_trace_mapper.js', + entrypoint: entryPoint, + ), + ); + assetServer.writeFile( + bootstrap, + generateMainModule(entrypoint: entryPoint), + ); + break; + case ModuleFormat.ddc: + assetServer.writeFile( + ddcModuleLoader, + ddcModuleLoaderJS.readAsStringSync(), + ); + String bootstrapper; + String mainModule; + if (compilerOptions.canaryFeatures) { + bootstrapper = generateDDCLibraryBundleBootstrapScript( + ddcModuleLoaderUrl: ddcModuleLoader, + mapperUrl: stackMapper, + entrypoint: entryPoint, + bootstrapUrl: bootstrap, + ); + const onLoadEndBootstrap = 'on_load_end_bootstrap.js'; + assetServer.writeFile( + onLoadEndBootstrap, + generateDDCLibraryBundleOnLoadEndBootstrap(), + ); + mainModule = generateDDCLibraryBundleMainModule( + entrypoint: entryPoint, + onLoadEndBootstrap: onLoadEndBootstrap, + ); + } else { + bootstrapper = generateDDCBootstrapScript( + ddcModuleLoaderUrl: ddcModuleLoader, + mapperUrl: stackMapper, + entrypoint: entryPoint, + bootstrapUrl: bootstrap, + ); + + // DDC uses a simple heuristic to determine exported identifier + // names. The module name (entrypoint name here) has its extension + // removed, and special path elements like '/', '\', and '..' are + // replaced with + // '__'. + final exportedMainName = pathToJSIdentifier( + entryPoint.split('.')[0], + ); + mainModule = generateDDCMainModule( + entrypoint: entryPoint, + exportedMain: exportedMainName, + ); + } + assetServer.writeFile(main, bootstrapper); + assetServer.writeFile(bootstrap, mainModule); + break; + default: + throw Exception('Unsupported DDC module format $ddcModuleFormat.'); + } + + assetServer.writeFile('main_module.digests', '{}'); + // Write an empty array of scripts to reload to handle the case where + // a test triggers a hot restart before any other action. + assetServer.writeFile('reloaded_sources.json', '[]'); + + final sdk = dartSdk; + final sdkSourceMap = dartSdkSourcemap; + assetServer.writeFile('dart_sdk.js', sdk.readAsStringSync()); + assetServer.writeFile('dart_sdk.js.map', sdkSourceMap.readAsStringSync()); + generator.reset(); + } + + final compilerOutput = await generator.recompile( + Uri.parse('org-dartlang-app:///$mainUri'), + invalidatedFiles, + outputPath: p.join(dillOutputPath, 'app.dill'), + packageConfig: packageUriMapper.packageConfig, + recompileRestart: fullRestart, + ); + if (compilerOutput == null || compilerOutput.errorCount > 0) { + return UpdateFSReport(success: false); + } + sources = compilerOutput.sources; + lastCompiled = DateTime.now(); + + File codeFile; + File manifestFile; + File sourcemapFile; + File metadataFile; + List modules; + try { + codeFile = outputDirectory.childFile( + '${compilerOutput.outputFilename}.sources', + ); + manifestFile = outputDirectory.childFile( + '${compilerOutput.outputFilename}.json', + ); + sourcemapFile = outputDirectory.childFile( + '${compilerOutput.outputFilename}.map', + ); + metadataFile = outputDirectory.childFile( + '${compilerOutput.outputFilename}.metadata', + ); + modules = assetServer.write( + codeFile, + manifestFile, + sourcemapFile, + metadataFile, + ); + } on FileSystemException catch (err) { + throw Exception('Failed to load recompiled sources:\n$err'); + } + if (ddcModuleFormat == ModuleFormat.ddc && + compilerOptions.canaryFeatures && + !initialCompile) { + writeReloadedSources(modules, fileServerUri!); + } + return UpdateFSReport( + success: true, + syncedBytes: codeFile.lengthSync(), + invalidatedSourcesCount: invalidatedFiles.length, + )..invalidatedModules = modules; + } + + static const String reloadedSourcesFileName = 'reloaded_sources.json'; + + /// Given a list of [modules] that need to be reloaded during a hot restart or + /// hot reload, writes a file that contains a list of objects each with three + /// fields: + /// + /// `src`: A string that corresponds to the file path containing a DDC library + /// bundle. + /// `module`: The name of the library bundle in `src`. + /// `libraries`: An array of strings containing the libraries that were + /// compiled in `src`. + /// + /// For example: + /// ```json + /// [ + /// { + /// "src": "/", + /// "module": "", + /// "libraries": ["", ""], + /// }, + /// ] + /// ``` + /// + /// The path of the output file should stay consistent across the lifetime of + /// the app. + void writeReloadedSources(List modules, Uri fileServerUri) { + final moduleToLibrary = >[]; + for (final module in modules) { + final metadata = ModuleMetadata.fromJson( + json.decode( + utf8.decode(assetServer.getMetadata('$module.metadata').toList()), + ) + as Map, + ); + final libraries = metadata.libraries.keys.toList(); + moduleToLibrary.add( + createReloadedSourceEntry( + src: '$fileServerUri/$module', + module: metadata.name, + libraries: libraries, + ), + ); + } + assetServer.writeFile( + reloadedSourcesFileName, + json.encode(moduleToLibrary), + ); + } + + static Map createReloadedSourceEntry({ + required String src, + required String module, + required List libraries, + }) => {'src': src, 'module': module, 'libraries': libraries}; + + File get ddcModuleLoaderJS => + fileSystem.file(sdkLayout.ddcModuleLoaderJsPath); + File get requireJS => fileSystem.file(sdkLayout.requireJsPath); + File get dartSdk => fileSystem.file(switch (ddcModuleFormat) { + ModuleFormat.amd => sdkLayout.amdJsPath, + ModuleFormat.ddc => sdkLayout.ddcJsPath, + _ => throw Exception('Unsupported DDC module format $ddcModuleFormat.'), + }); + File get dartSdkSourcemap => fileSystem.file(switch (ddcModuleFormat) { + ModuleFormat.amd => sdkLayout.amdJsMapPath, + ModuleFormat.ddc => sdkLayout.ddcJsMapPath, + _ => throw Exception('Unsupported DDC module format $ddcModuleFormat.'), + }); + File get stackTraceMapper => fileSystem.file(sdkLayout.stackTraceMapperPath); + ModuleFormat get ddcModuleFormat => compilerOptions.moduleFormat; +} + +class UpdateFSReport { + final bool _success; + final int _invalidatedSourcesCount; + final int _syncedBytes; + + UpdateFSReport({ + this._success = false, + this._invalidatedSourcesCount = 0, + this._syncedBytes = 0, + }); + + bool get success => _success; + int get invalidatedSourcesCount => _invalidatedSourcesCount; + int get syncedBytes => _syncedBytes; + + /// JavaScript modules produced by the incremental compiler in `dartdevc` + /// mode. + /// + /// Only used for JavaScript compilation. + List? invalidatedModules; +} + +/// The result of an invalidation check from [ProjectFileInvalidator]. +class InvalidationResult { + const InvalidationResult({this.uris}); + + final List? uris; +} + +/// The [ProjectFileInvalidator] track the dependencies for a running +/// application to determine when they are dirty. +class ProjectFileInvalidator { + ProjectFileInvalidator({required this._fileSystem}); + + final FileSystem _fileSystem; + + static const String _pubCachePathLinuxAndMac = '.pub-cache'; + static const String _pubCachePathWindows = 'Pub/Cache'; + + Future findInvalidated({ + required DateTime? lastCompiled, + required List urisToMonitor, + required String packagesPath, + }) async { + if (lastCompiled == null) { + // Initial load. + assert(urisToMonitor.isEmpty); + return const InvalidationResult(uris: []); + } + + final urisToScan = [ + // Don't watch pub cache directories to speed things up a little. + for (final Uri uri in urisToMonitor) + if (_isNotInPubCache(uri)) uri, + ]; + final invalidatedFiles = []; + for (final uri in urisToScan) { + // Calling fs.statSync() is more performant than fs.file().statSync(), + // but uri.toFilePath() does not work with MultiRootFileSystem. + final updatedAt = uri.hasScheme && uri.scheme != 'file' + ? _fileSystem.file(uri).statSync().modified + : _fileSystem + .statSync(uri.toFilePath(windows: Platform.isWindows)) + .modified; + if (updatedAt.isAfter(lastCompiled)) { + invalidatedFiles.add(uri); + } + } + // We need to check the .dart_tool/package_config.json file too since it is + // not used in compilation. + final packageFile = _fileSystem.file(packagesPath); + final packageUri = packageFile.uri; + final updatedAt = packageFile.statSync().modified; + if (updatedAt.isAfter(lastCompiled)) { + invalidatedFiles.add(packageUri); + } + + return InvalidationResult(uris: invalidatedFiles); + } + + bool _isNotInPubCache(Uri uri) { + return !(Platform.isWindows && uri.path.contains(_pubCachePathWindows)) && + !uri.path.contains(_pubCachePathLinuxAndMac); + } +} diff --git a/dwds_test_common/lib/frontend_server_common/frontend_server_client.dart b/dwds_test_common/lib/frontend_server_common/frontend_server_client.dart new file mode 100644 index 0000000000..9c3ee5d2c1 --- /dev/null +++ b/dwds_test_common/lib/frontend_server_common/frontend_server_client.dart @@ -0,0 +1,726 @@ +// Copyright 2020 The Dart Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Note: this is a copy from flutter tools, updated to work with dwds tests + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/test_sdk_layout.dart'; +import 'package:logging/logging.dart'; +import 'package:package_config/package_config.dart'; + +import 'utilities.dart'; +import 'uuid.dart'; + +Logger _logger = Logger('FrontendServerClient'); +Logger _serverLogger = Logger('FrontendServer'); + +void defaultConsumer(String message, {StackTrace? stackTrace}) => + stackTrace == null + ? _serverLogger.info(message) + : _serverLogger.severe(message, null, stackTrace); + +typedef CompilerMessageConsumer = + void Function(String message, {StackTrace stackTrace}); + +class CompilerOutput { + const CompilerOutput(this.outputFilename, this.errorCount, this.sources); + + final String outputFilename; + final int errorCount; + final List sources; +} + +enum StdoutState { collectDiagnostic, collectDependencies } + +/// Handles stdin/stdout communication with the frontend server. +class StdoutHandler { + StdoutHandler({required this.consumer}) { + reset(); + } + + final CompilerMessageConsumer consumer; + late Completer compilerOutput; + + final List _sources = []; + + bool _compilerMessageReceived = false; + String? _boundaryKey; + StdoutState _state = StdoutState.collectDiagnostic; + late bool _suppressCompilerMessages; + late bool _expectSources; + bool _badState = false; + + void handler(String message) { + if (message.startsWith('Observatory listening')) { + stderr.writeln(message); + return; + } + if (message.startsWith('Observatory server failed')) { + throw Exception(message); + } + if (_badState) { + return; + } + final kResultPrefix = 'result '; + if (_boundaryKey == null && message.startsWith(kResultPrefix)) { + _boundaryKey = message.substring(kResultPrefix.length); + return; + } + // Invalid state, see commented issue below for more information. + // NB: both the completeError and _badState flags are required to avoid + // filling the console with exceptions. + if (_boundaryKey == null) { + // Throwing a synchronous exception via throwToolExit will fail to cancel + // the stream. Instead use completeError so that the error is returned + // from the awaited future that the compiler consumers are expecting. + compilerOutput.completeError( + 'Frontend server tests encountered an internal problem. ' + 'This can be caused by printing to stdout into the stream that is ' + 'used for communication between frontend server (in sdk) or ' + 'frontend server client (in dwds tests).' + '\n\n' + 'Additional debugging information:\n' + ' StdoutState: $_state\n' + ' compilerMessageReceived: $_compilerMessageReceived\n' + ' message: $message\n' + ' _expectSources: $_expectSources\n' + ' sources: $_sources\n', + ); + // There are several event turns before the tool actually exits from a + // tool exception. Normally, the stream should be cancelled to prevent + // more events from entering the bad state, but because the error + // is coming from handler itself, there is no clean way to pipe this + // through. Instead, we set a flag to prevent more messages from + // registering. + _badState = true; + return; + } + final boundaryKey = _boundaryKey!; + if (message.startsWith(boundaryKey)) { + if (_expectSources) { + if (_state == StdoutState.collectDiagnostic) { + _state = StdoutState.collectDependencies; + return; + } + } + if (message.length <= boundaryKey.length) { + compilerOutput.complete(null); + return; + } + final spaceDelimiter = message.lastIndexOf(' '); + compilerOutput.complete( + CompilerOutput( + message.substring(boundaryKey.length + 1, spaceDelimiter), + int.parse(message.substring(spaceDelimiter + 1).trim()), + _sources, + ), + ); + return; + } + if (_state == StdoutState.collectDiagnostic) { + if (!_suppressCompilerMessages) { + if (_compilerMessageReceived == false) { + consumer('\nCompiler message:'); + _compilerMessageReceived = true; + } + consumer(message); + } + } else { + assert(_state == StdoutState.collectDependencies); + switch (message[0]) { + case '+': + _sources.add(Uri.parse(message.substring(1))); + break; + case '-': + _sources.remove(Uri.parse(message.substring(1))); + break; + default: + _logger.warning('Unexpected prefix for $message uri - ignoring'); + } + } + } + + // This is needed to get ready to process next compilation result output, + // with its own boundary key and new completer. + void reset({ + bool suppressCompilerMessages = false, + bool expectSources = true, + }) { + _boundaryKey = null; + _compilerMessageReceived = false; + compilerOutput = Completer(); + _suppressCompilerMessages = suppressCompilerMessages; + _expectSources = expectSources; + _state = StdoutState.collectDiagnostic; + } +} + +/// Class that allows to serialize compilation requests to the compiler. +abstract class _CompilationRequest { + _CompilationRequest(this.completer); + + Completer completer; + + Future _run(ResidentCompiler compiler); + + Future run(ResidentCompiler compiler) async { + completer.complete(await _run(compiler)); + } +} + +class _RecompileRequest extends _CompilationRequest { + _RecompileRequest( + super.completer, + this.mainUri, + this.invalidatedFiles, + this.outputPath, + this.packageConfig, { + required this.recompileRestart, + }); + + Uri mainUri; + List invalidatedFiles; + String outputPath; + PackageConfig packageConfig; + bool recompileRestart; + + @override + Future _run(ResidentCompiler compiler) async => + compiler._recompile(this); +} + +class _CompileExpressionRequest extends _CompilationRequest { + _CompileExpressionRequest( + super.completer, + this.expression, + this.definitions, + this.typeDefinitions, + this.libraryUri, + this.scriptUri, + this.klass, + this.isStatic, + ); + + String expression; + List definitions; + List typeDefinitions; + String? libraryUri; + String? scriptUri; + String? klass; + bool? isStatic; + + @override + Future _run(ResidentCompiler compiler) async => + compiler._compileExpression(this); +} + +class _CompileExpressionToJsRequest extends _CompilationRequest { + _CompileExpressionToJsRequest( + super.completer, + this.libraryUri, + this.scriptUri, + this.line, + this.column, + this.jsModules, + this.jsFrameValues, + this.moduleName, + this.expression, + ); + + String libraryUri; + String scriptUri; + int line; + int column; + Map jsModules; + Map jsFrameValues; + String moduleName; + String expression; + + @override + Future _run(ResidentCompiler compiler) async => + compiler._compileExpressionToJs(this); +} + +class _RejectRequest extends _CompilationRequest { + _RejectRequest(super.completer); + + @override + Future _run(ResidentCompiler compiler) async => + compiler._reject(); +} + +/// Wrapper around incremental frontend server compiler, that communicates with +/// server via stdin/stdout. +/// +/// The wrapper is intended to stay resident in memory as user changes, reloads, +/// restarts the Flutter app. +class ResidentCompiler { + ResidentCompiler( + this.sdkRoot, { + required this.projectDirectory, + required this.packageConfigFile, + required this.useDebuggerModuleNames, + required this.fileSystemRoots, + required this.fileSystemScheme, + required this.platformDill, + required this.compilerOptions, + required this.sdkLayout, + this.verbose = false, + CompilerMessageConsumer compilerMessageConsumer = defaultConsumer, + }) : _stdoutHandler = StdoutHandler(consumer: compilerMessageConsumer); + + final Uri projectDirectory; + final Uri packageConfigFile; + final bool useDebuggerModuleNames; + final List fileSystemRoots; + final String fileSystemScheme; + final String platformDill; + final TestSdkLayout sdkLayout; + final CompilerOptions compilerOptions; + final bool verbose; + + /// The path to the root of the Dart SDK used to compile. + final String sdkRoot; + + Process? _server; + final StdoutHandler _stdoutHandler; + bool _compileRequestNeedsConfirmation = false; + + final StreamController<_CompilationRequest> _controller = + StreamController<_CompilationRequest>(); + + /// If invoked for the first time, it compiles Dart script identified by + /// [mainUri], [invalidatedFiles] list is ignored. + /// On successive runs [invalidatedFiles] indicates which files need to be + /// recompiled. If [mainUri] is null, previously used [mainUri] entry + /// point that is used for recompilation. + /// Binary file name is returned if compilation was successful, otherwise + /// null is returned. + /// If [recompileRestart] is true, uses the `recompile-restart` instruction + /// instead of `recompile`. + Future recompile( + Uri mainUri, + List invalidatedFiles, { + required String outputPath, + required PackageConfig packageConfig, + required bool recompileRestart, + }) async { + if (!_controller.hasListener) { + _controller.stream.listen(_handleCompilationRequest); + } + + final completer = Completer(); + _controller.add( + _RecompileRequest( + completer, + mainUri, + invalidatedFiles, + outputPath, + packageConfig, + recompileRestart: recompileRestart, + ), + ); + return completer.future; + } + + Future _recompile(_RecompileRequest request) async { + _stdoutHandler.reset(); + + final mainUri = + request.packageConfig.toPackageUri(request.mainUri)?.toString() ?? + _toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots); + + _compileRequestNeedsConfirmation = true; + + if (_server == null) { + return _compile(mainUri, request.outputPath); + } + final server = _server!; + + final inputKey = generateV4UUID(); + final instruction = request.recompileRestart + ? 'recompile-restart' + : 'recompile'; + server.stdin.writeln('$instruction $mainUri $inputKey'); + _logger.info('<- $instruction $mainUri $inputKey'); + for (final fileUri in request.invalidatedFiles) { + String message; + if (fileUri.scheme == 'package') { + message = fileUri.toString(); + } else { + message = + request.packageConfig.toPackageUri(fileUri)?.toString() ?? + _toMultiRootPath(fileUri, fileSystemScheme, fileSystemRoots); + } + server.stdin.writeln(message); + _logger.info(message); + } + server.stdin.writeln(inputKey); + _logger.info('<- $inputKey'); + + return _stdoutHandler.compilerOutput.future; + } + + final List<_CompilationRequest> _compilationQueue = <_CompilationRequest>[]; + + Future _handleCompilationRequest(_CompilationRequest request) async { + final isEmpty = _compilationQueue.isEmpty; + _compilationQueue.add(request); + // Only trigger processing if queue was empty - i.e. no other requests + // are currently being processed. This effectively enforces "one + // compilation request at a time". + if (isEmpty) { + while (_compilationQueue.isNotEmpty) { + final request = _compilationQueue.first; + await request.run(this); + _compilationQueue.removeAt(0); + } + } + } + + Future _compile( + String scriptUri, + String outputFilePath, + ) async { + final frontendServer = sdkLayout.frontendServerSnapshotPath; + final args = [ + frontendServer, + '--sdk-root', + sdkRoot, + '--incremental', + '--target=dartdevc', + '-Ddart.developer.causal_async_stacks=true', + '--output-dill', + outputFilePath, + ...['--packages', '$packageConfigFile'], + for (final root in fileSystemRoots) ...[ + '--filesystem-root', + '$root', + ], + ...['--filesystem-scheme', fileSystemScheme], + ...['--platform', platformDill], + if (useDebuggerModuleNames) '--debugger-module-names', + '--experimental-emit-debug-metadata', + for (final experiment in compilerOptions.experiments) + '--enable-experiment=$experiment', + if (compilerOptions.canaryFeatures) '--dartdevc-canary', + if (verbose) '--verbose', + if (compilerOptions.moduleFormat == ModuleFormat.ddc) + '--dartdevc-module-format=ddc', + ]; + _logger.info(args.join(' ')); + final workingDirectory = projectDirectory.toFilePath(); + _server = await Process.start( + sdkLayout.dartAotRuntimePath, + args, + workingDirectory: workingDirectory, + ); + + final server = _server!; + server.stdout + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen( + _stdoutHandler.handler, + onDone: () { + // when outputFilename future is not completed, but stdout is closed + // process has died unexpectedly. + if (!_stdoutHandler.compilerOutput.isCompleted) { + _stdoutHandler.compilerOutput.complete(null); + throw Exception('the Dart compiler exited unexpectedly.'); + } + }, + ); + + server.stderr + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen(_logger.info); + + unawaited( + server.exitCode.then((int code) { + if (code != 0) { + throw Exception('the Dart compiler exited unexpectedly.'); + } + }), + ); + + server.stdin.writeln('compile $scriptUri'); + _logger.info('<- compile $scriptUri'); + + return _stdoutHandler.compilerOutput.future; + } + + /// Compile dart expression to kernel. + Future compileExpression( + String expression, + List definitions, + List typeDefinitions, + String libraryUri, + String scriptUri, + String klass, + bool isStatic, + ) { + if (!_controller.hasListener) { + _controller.stream.listen(_handleCompilationRequest); + } + + final completer = Completer(); + _controller.add( + _CompileExpressionRequest( + completer, + expression, + definitions, + typeDefinitions, + libraryUri, + scriptUri, + klass, + isStatic, + ), + ); + return completer.future; + } + + Future _compileExpression( + _CompileExpressionRequest request, + ) async { + _stdoutHandler.reset(suppressCompilerMessages: true, expectSources: false); + + // 'compile-expression' should be invoked after compiler has been started, + // program was compiled. + if (_server == null) { + return null; + } + final server = _server!; + + final inputKey = generateV4UUID(); + server.stdin.writeln('compile-expression $inputKey'); + server.stdin.writeln(request.expression); + request.definitions.forEach(server.stdin.writeln); + server.stdin.writeln(inputKey); + request.typeDefinitions.forEach(server.stdin.writeln); + server.stdin.writeln(inputKey); + server.stdin.writeln(request.libraryUri ?? ''); + server.stdin.writeln(request.klass ?? ''); + server.stdin.writeln(request.isStatic ?? false); + + return _stdoutHandler.compilerOutput.future; + } + + /// Compiles dart expression to JavaScript. + Future compileExpressionToJs( + String libraryUri, + String scriptUri, + int line, + int column, + Map jsModules, + Map jsFrameValues, + String moduleName, + String expression, + ) { + if (!_controller.hasListener) { + _controller.stream.listen(_handleCompilationRequest); + } + + final completer = Completer(); + _controller.add( + _CompileExpressionToJsRequest( + completer, + libraryUri, + scriptUri, + line, + column, + jsModules, + jsFrameValues, + moduleName, + expression, + ), + ); + return completer.future; + } + + Future _compileExpressionToJs( + _CompileExpressionToJsRequest request, + ) async { + _stdoutHandler.reset( + suppressCompilerMessages: !verbose, + expectSources: false, + ); + + // Compiling an expression should happen after the compiler has been + // started and the program was compiled. + if (_server == null) { + return null; + } + final server = _server!; + + server.stdin.writeln('JSON_INPUT'); + server.stdin.writeln( + json.encode({ + 'type': 'COMPILE_EXPRESSION_JS', + 'data': { + 'expression': request.expression, + 'libraryUri': request.libraryUri, + 'scriptUri': request.scriptUri, + 'line': request.line, + 'column': request.column, + 'jsModules': request.jsModules, + 'jsFrameValues': request.jsFrameValues, + 'moduleName': request.moduleName, + }, + }), + ); + + return _stdoutHandler.compilerOutput.future; + } + + /// Should be invoked when results of compilation are accepted by the client. + /// + /// Either [accept] or [reject] should be called after every [recompile] call. + void accept() { + if (_compileRequestNeedsConfirmation) { + _server!.stdin.writeln('accept'); + _logger.info('<- accept'); + } + _compileRequestNeedsConfirmation = false; + } + + /// Should be invoked when results of compilation are rejected by the client. + /// + /// Either [accept] or [reject] should be called after every [recompile] call. + Future reject() { + if (!_controller.hasListener) { + _controller.stream.listen(_handleCompilationRequest); + } + + final completer = Completer(); + _controller.add(_RejectRequest(completer)); + return completer.future; + } + + Future _reject() { + if (!_compileRequestNeedsConfirmation) { + return Future.value(null); + } + _stdoutHandler.reset(expectSources: false); + _server!.stdin.writeln('reject'); + _logger.info('<- reject'); + _compileRequestNeedsConfirmation = false; + return _stdoutHandler.compilerOutput.future; + } + + /// Should be invoked when frontend server compiler should forget what was + /// accepted previously so that next call to [recompile] produces complete + /// kernel file. + void reset() { + // TODO(annagrin): make sure this works when we support hot restart in + // tests using frontend server - for example, throw an error if the + // server is not available. + _server?.stdin.writeln('reset'); + _logger.info('<- reset'); + } + + Future quit() async { + _server?.stdin.writeln('quit'); + _logger.info('<- quit'); + + if (_server == null) { + return 0; + } + return _server!.exitCode; + } + + /// stop the service normally + Future shutdown() async { + // Server was never successfully created. + if (_server == null) { + return 0; + } + return quit(); + } + + /// kill the service + Future kill() async { + if (_server == null) { + return 0; + } + + final server = _server!; + _logger.info('killing pid ${server.pid}'); + server.kill(); + return server.exitCode; + } +} + +class TestExpressionCompiler implements ExpressionCompiler { + final ResidentCompiler _generator; + TestExpressionCompiler(this._generator); + + @override + Future compileExpressionToJs( + String isolateId, + String libraryUri, + String scriptUri, + int line, + int column, + Map jsModules, + Map jsFrameValues, + String moduleName, + String expression, + ) async { + final compilerOutput = await _generator.compileExpressionToJs( + libraryUri, + scriptUri, + line, + column, + jsModules, + jsFrameValues, + moduleName, + expression, + ); + + if (compilerOutput != null) { + final content = utf8.decode( + localFileSystem.file(compilerOutput.outputFilename).readAsBytesSync(), + ); + return ExpressionCompilationResult( + content, + compilerOutput.errorCount > 0, + ); + } + + throw Exception('Failed to compile $expression'); + } + + @override + Future updateDependencies(Map modules) async => + true; + + @override + Future initialize(CompilerOptions options) async {} +} + +/// Convert a file URI into a multi-root scheme URI if provided, otherwise +/// return unmodified. +String _toMultiRootPath( + Uri fileUri, + String? scheme, + List fileSystemRoots, +) { + if (scheme == null || fileSystemRoots.isEmpty || fileUri.scheme != 'file') { + return fileUri.toString(); + } + final filePath = fileUri.toFilePath(windows: Platform.isWindows); + for (final fileSystemRoot in fileSystemRoots) { + final rootPath = fileSystemRoot.toFilePath(windows: Platform.isWindows); + if (filePath.startsWith(rootPath)) { + return '$scheme:///${filePath.substring(rootPath.length)}'; + } + } + return fileUri.toString(); +} diff --git a/dwds_test_common/lib/frontend_server_common/resident_runner.dart b/dwds_test_common/lib/frontend_server_common/resident_runner.dart new file mode 100644 index 0000000000..905d7c61db --- /dev/null +++ b/dwds_test_common/lib/frontend_server_common/resident_runner.dart @@ -0,0 +1,154 @@ +// Copyright 2020 The Dart Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Note: this is a copy from flutter tools, updated to work with dwds tests, +// and some functionality removed (does not support hot reload yet) + +import 'dart:async'; + +import 'package:dwds/asset_reader.dart'; +import 'package:dwds/config.dart'; +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/test_sdk_layout.dart'; +import 'package:file/file.dart'; +import 'package:logging/logging.dart'; + +import 'devfs.dart'; +import 'frontend_server_client.dart'; + +class ResidentWebRunner { + final _logger = Logger('ResidentWebRunner'); + + ResidentWebRunner({ + required this.mainUri, + required this.urlTunneler, + required this.projectDirectory, + required this.packageConfigFile, + required this.packageUriMapper, + required this.fileSystemRoots, + required this.fileSystemScheme, + required this.outputPath, + required this.compilerOptions, + required this.sdkLayout, + bool verbose = false, + }) { + final platformDillUri = Uri.file(sdkLayout.summaryPath); + + generator = ResidentCompiler( + sdkLayout.sdkDirectory, + projectDirectory: projectDirectory, + packageConfigFile: packageConfigFile, + useDebuggerModuleNames: packageUriMapper.useDebuggerModuleNames, + platformDill: '$platformDillUri', + fileSystemRoots: fileSystemRoots, + fileSystemScheme: fileSystemScheme, + compilerOptions: compilerOptions, + sdkLayout: sdkLayout, + verbose: verbose, + ); + expressionCompiler = TestExpressionCompiler(generator); + } + + final UrlEncoder? urlTunneler; + final Uri mainUri; + final Uri projectDirectory; + final Uri packageConfigFile; + final PackageUriMapper packageUriMapper; + final String outputPath; + final List fileSystemRoots; + final String fileSystemScheme; + final CompilerOptions compilerOptions; + final TestSdkLayout sdkLayout; + + late ResidentCompiler generator; + late ExpressionCompiler expressionCompiler; + ProjectFileInvalidator? _projectFileInvalidator; + WebDevFS? devFS; + Uri? uri; + + Future run( + FileSystem fileSystem, { + String? hostname, + required int port, + required String index, + }) async { + _projectFileInvalidator ??= ProjectFileInvalidator(fileSystem: fileSystem); + devFS ??= WebDevFS( + fileSystem: fileSystem, + hostname: hostname ?? 'localhost', + port: port, + projectDirectory: projectDirectory, + packageUriMapper: packageUriMapper, + index: index, + urlTunneler: urlTunneler, + sdkLayout: sdkLayout, + compilerOptions: compilerOptions, + ); + uri ??= await devFS!.create(); + + final report = await _updateDevFS( + initialCompile: true, + fullRestart: false, + fileServerUri: null, + ); + if (!report.success) { + _logger.severe('Failed to compile application.'); + return 1; + } + + generator.accept(); + return 0; + } + + Future rerun({ + required bool fullRestart, + // The uri of the `HttpServer` that handles file requests. + // TODO(srujzs): This should be the same as the uri of the AssetServer to + // align with Flutter tools, but currently is not. Delete when that's fixed. + required Uri fileServerUri, + }) async { + final report = await _updateDevFS( + initialCompile: false, + fullRestart: fullRestart, + fileServerUri: fileServerUri, + ); + if (!report.success) { + _logger.severe('Failed to compile application.'); + return 1; + } + + generator.accept(); + return 0; + } + + Future _updateDevFS({ + required bool initialCompile, + required bool fullRestart, + // The uri of the `TestServer` that handles file requests. + // TODO(srujzs): This should be the same as the uri of the AssetServer to + // align with Flutter tools, but currently is not. Delete when that's fixed. + required Uri? fileServerUri, + }) async { + final invalidationResult = await _projectFileInvalidator!.findInvalidated( + lastCompiled: devFS!.lastCompiled, + urisToMonitor: devFS!.sources, + packagesPath: packageConfigFile.toFilePath(), + ); + final report = await devFS!.update( + mainUri: mainUri, + dillOutputPath: outputPath, + generator: generator, + invalidatedFiles: invalidationResult.uris!, + initialCompile: initialCompile, + fullRestart: fullRestart, + fileServerUri: fileServerUri, + ); + return report; + } + + Future stop() async { + await generator.shutdown(); + await devFS!.dispose(); + } +} diff --git a/dwds_test_common/lib/frontend_server_common/utilities.dart b/dwds_test_common/lib/frontend_server_common/utilities.dart new file mode 100644 index 0000000000..eddc3b40ac --- /dev/null +++ b/dwds_test_common/lib/frontend_server_common/utilities.dart @@ -0,0 +1,8 @@ +// Copyright (c) 2019, 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:file/file.dart' as fs; +import 'package:file/local.dart'; + +const fs.FileSystem localFileSystem = LocalFileSystem(); diff --git a/dwds_test_common/lib/frontend_server_common/uuid.dart b/dwds_test_common/lib/frontend_server_common/uuid.dart new file mode 100644 index 0000000000..b375a98a1b --- /dev/null +++ b/dwds_test_common/lib/frontend_server_common/uuid.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2024, 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:math' show Random; + +/// A UUID generator. +/// +/// The generated values are 128 bit numbers encoded in a specific string +/// format. +/// +/// Generate a version 4 (random) uuid. This is a uuid scheme that only uses +/// random numbers as the source of the generated uuid. +String generateV4UUID() { + final special = 8 + _random.nextInt(4); + + return '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}-' + '${_bitsDigits(16, 4)}-' + '4${_bitsDigits(12, 3)}-' + '${_printDigits(special, 1)}${_bitsDigits(12, 3)}-' + '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}'; +} + +final Random _random = Random(); + +String _bitsDigits(int bitCount, int digitCount) => + _printDigits(_generateBits(bitCount), digitCount); + +int _generateBits(int bitCount) => _random.nextInt(1 << bitCount); + +String _printDigits(int value, int count) => + value.toRadixString(16).padLeft(count, '0'); diff --git a/dwds_test_common/lib/integration/README.md b/dwds_test_common/lib/integration/README.md new file mode 100644 index 0000000000..8225231ffe --- /dev/null +++ b/dwds_test_common/lib/integration/README.md @@ -0,0 +1,5 @@ +# DWDS Shared Integration Tests + +This directory contains shared integration test scenarios for DWDS. + +These tests are meant to be provided a build context by the test caller, such as `frontend_server` or `build_daemon`, allowing the same debugging and inspection workflows to be verified across different build clients. diff --git a/dwds/test/integration/handlers/asset_handler_common.dart b/dwds_test_common/lib/integration/asset_handler.dart similarity index 86% rename from dwds/test/integration/handlers/asset_handler_common.dart rename to dwds_test_common/lib/integration/asset_handler.dart index 7f3ba6362f..00716cab91 100644 --- a/dwds/test/integration/handlers/asset_handler_common.dart +++ b/dwds_test_common/lib/integration/asset_handler.dart @@ -2,18 +2,20 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:shelf/shelf.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import '../fixtures/project.dart'; -import '../fixtures/utilities.dart'; - -void testAll({required TestSdkConfigurationProvider provider}) { +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { group('Asset handler', () { - final context = TestContext(TestProject.test, provider); + final context = contextFactory(TestProject.test, provider); setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); diff --git a/dwds/test/integration/breakpoint_common.dart b/dwds_test_common/lib/integration/breakpoint.dart similarity index 96% rename from dwds/test/integration/breakpoint_common.dart rename to dwds_test_common/lib/integration/breakpoint.dart index 88dea2d2a9..7bbda8cbc2 100644 --- a/dwds/test/integration/breakpoint_common.dart +++ b/dwds_test_common/lib/integration/breakpoint.dart @@ -2,29 +2,27 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:vm_service_interface/vm_service_interface.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - void testBreakpoint({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, bool verboseCompiler = false, }) { - final context = TestContext(TestProject.testPackage(), provider); + final context = contextFactory(TestProject.testPackage(), provider); group('shared context', () { setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, verboseCompiler: verboseCompiler, canaryFeatures: provider.canaryFeatures, moduleFormat: provider.ddcModuleFormat, diff --git a/dwds/test/integration/callstack_common.dart b/dwds_test_common/lib/integration/callstack.dart similarity index 97% rename from dwds/test/integration/callstack_common.dart rename to dwds_test_common/lib/integration/callstack.dart index e0782f6e4e..6af10a3360 100644 --- a/dwds/test/integration/callstack_common.dart +++ b/dwds_test_common/lib/integration/callstack.dart @@ -2,30 +2,28 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:vm_service_interface/vm_service_interface.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - void testCallStack({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, bool verboseCompiler = false, }) { final project = TestProject.testPackage(); - final context = TestContext(project, provider); + final context = contextFactory(project, provider); group('shared context |', () { setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, verboseCompiler: verboseCompiler, moduleFormat: provider.ddcModuleFormat, diff --git a/dwds/test/integration/common/chrome_proxy_service_common.dart b/dwds_test_common/lib/integration/chrome_proxy_service.dart similarity index 85% rename from dwds/test/integration/common/chrome_proxy_service_common.dart rename to dwds_test_common/lib/integration/chrome_proxy_service.dart index 306fa02c90..23dada420d 100644 --- a/dwds/test/integration/common/chrome_proxy_service_common.dart +++ b/dwds_test_common/lib/integration/chrome_proxy_service.dart @@ -15,6 +15,9 @@ import 'package:dwds/expression_compiler.dart'; import 'package:dwds/src/services/chrome/chrome_proxy_service.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; import 'package:dwds/src/utilities/shared.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:http/http.dart' as http; @@ -23,18 +26,14 @@ import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:vm_service_interface/vm_service_interface.dart'; -import '../fixtures/context.dart'; -import '../fixtures/project.dart'; -import '../fixtures/utilities.dart'; - void runTests({ required TestSdkConfigurationProvider provider, required ModuleFormat moduleFormat, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { final project = TestProject.test; - final context = TestContext(project, provider); + final context = contextFactory(project, provider); group('shared context', () { setUpAll(() async { @@ -45,7 +44,6 @@ void runTests({ verboseCompiler: false, moduleFormat: provider.ddcModuleFormat, canaryFeatures: canaryFeatures, - compilationMode: compilationMode, ), ); }); @@ -470,10 +468,11 @@ void runTests({ Future createRemoteObject(String message) async { return await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'createObject("$message")', - ) as InstanceRef; + isolate.id!, + bootstrap!.id!, + 'createObject("$message")', + ) + as InstanceRef; } test('single scope object', () async { @@ -637,10 +636,12 @@ void runTests({ }); test('Classes', () async { - final testClass = await service.getObject( - isolate.id!, - rootLibrary!.classes!.first.id!, - ) as Class; + final testClass = + await service.getObject( + isolate.id!, + rootLibrary!.classes!.first.id!, + ) + as Class; expect( testClass.functions, unorderedEquals([ @@ -682,41 +683,42 @@ void runTests({ }); test('Runtime classes', () async { - final testClass = await service.getObject( - isolate.id!, - 'classes|dart:_runtime|_Type', - ) as Class; + final testClass = + await service.getObject(isolate.id!, 'classes|dart:_runtime|_Type') + as Class; expect(testClass.name, '_Type'); }); test('String', () async { - final worldRef = await service.evaluate( - isolate.id!, - bootstrap!.id!, - "helloString('world')", - ) as InstanceRef; + final worldRef = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + "helloString('world')", + ) + as InstanceRef; final world = await service.getObject(isolate.id!, worldRef.id!) as Instance; expect(world.valueAsString, 'world'); }); test('Large strings not truncated', () async { - final largeString = await service.evaluate( - isolate.id!, - bootstrap!.id!, - "helloString('${'abcde' * 250}')", - ) as InstanceRef; + final largeString = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + "helloString('${'abcde' * 250}')", + ) + as InstanceRef; expect(largeString.valueAsStringIsTruncated, isNot(isTrue)); expect(largeString.valueAsString!.length, largeString.length); expect(largeString.length, 5 * 250); }); test('Lists', () async { - final list = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelList', - ) as InstanceRef; + final list = + await service.evaluate(isolate.id!, bootstrap!.id!, 'topLevelList') + as InstanceRef; final inst = await service.getObject(isolate.id!, list.id!) as Instance; expect(inst.length, 1001); expect(inst.offset, null); @@ -729,11 +731,9 @@ void runTests({ }); test('Maps', () async { - final map = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelMap', - ) as InstanceRef; + final map = + await service.evaluate(isolate.id!, bootstrap!.id!, 'topLevelMap') + as InstanceRef; final inst = await service.getObject(isolate.id!, map.id!) as Instance; expect(inst.length, 1001); expect(inst.offset, null); @@ -748,11 +748,13 @@ void runTests({ }); test('bool', () async { - final ref = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'helloBool(true)', - ) as InstanceRef; + final ref = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'helloBool(true)', + ) + as InstanceRef; final obj = await service.getObject(isolate.id!, ref.id!) as Instance; expect(obj.kind, InstanceKind.kBool); expect(obj.classRef!.name, 'Bool'); @@ -760,11 +762,9 @@ void runTests({ }); test('num', () async { - final ref = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'helloNum(42)', - ) as InstanceRef; + final ref = + await service.evaluate(isolate.id!, bootstrap!.id!, 'helloNum(42)') + as InstanceRef; final obj = await service.getObject(isolate.id!, ref.id!) as Instance; expect(obj.kind, InstanceKind.kDouble); expect(obj.classRef!.name, 'Double'); @@ -789,17 +789,21 @@ void runTests({ group('getObject called with offset/count parameters', () { test('Lists with null offset and count are not truncated', () async { - final list = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelList', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - list.id!, - count: null, - offset: null, - ) as Instance; + final list = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelList', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + list.id!, + count: null, + offset: null, + ) + as Instance; expect(inst.length, 1001); expect(inst.offset, null); expect(inst.count, null); @@ -811,17 +815,21 @@ void runTests({ }); test('Lists with null count are not truncated', () async { - final list = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelList', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - list.id!, - count: null, - offset: 0, - ) as Instance; + final list = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelList', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + list.id!, + count: null, + offset: 0, + ) + as Instance; expect(inst.length, 1001); expect(inst.offset, 0); expect(inst.count, null); @@ -834,17 +842,21 @@ void runTests({ test('Lists with null count and offset greater than 0 are ' 'truncated from offset to end of list', () async { - final list = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelList', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - list.id!, - count: null, - offset: 1000, - ) as Instance; + final list = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelList', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + list.id!, + count: null, + offset: 1000, + ) + as Instance; expect(inst.length, 1001); expect(inst.offset, 1000); expect(inst.count, null); @@ -854,17 +866,21 @@ void runTests({ }); test('Lists with offset/count are truncated', () async { - final list = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelList', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - list.id!, - count: 7, - offset: 4, - ) as Instance; + final list = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelList', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + list.id!, + count: 7, + offset: 4, + ) + as Instance; expect(inst.length, 1001); expect(inst.offset, 4); expect(inst.count, 7); @@ -878,17 +894,21 @@ void runTests({ test( 'Lists are truncated to the end if offset/count runs off the end', () async { - final list = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelList', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - list.id!, - count: 5, - offset: 1000, - ) as Instance; + final list = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelList', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + list.id!, + count: 5, + offset: 1000, + ) + as Instance; expect(inst.length, 1001); expect(inst.offset, 1000); expect(inst.count, 1); @@ -901,17 +921,21 @@ void runTests({ test( 'Lists are truncated to empty if offset runs off the end', () async { - final list = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelList', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - list.id!, - count: 5, - offset: 1002, - ) as Instance; + final list = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelList', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + list.id!, + count: 5, + offset: 1002, + ) + as Instance; expect(inst.elements!.length, 0); expect(inst.length, 1001); expect(inst.offset, 1002); @@ -923,17 +947,21 @@ void runTests({ test( 'Lists are truncated to empty with 0 count and null offset', () async { - final list = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelList', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - list.id!, - count: 0, - offset: null, - ) as Instance; + final list = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelList', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + list.id!, + count: 0, + offset: null, + ) + as Instance; expect(inst.elements!.length, 0); expect(inst.length, 1001); expect(inst.offset, null); @@ -943,17 +971,17 @@ void runTests({ ); test('Maps with null offset/count are not truncated', () async { - final map = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelMap', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - map.id!, - count: null, - offset: null, - ) as Instance; + final map = + await service.evaluate(isolate.id!, bootstrap!.id!, 'topLevelMap') + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + map.id!, + count: null, + offset: null, + ) + as Instance; expect(inst.length, 1001); expect(inst.offset, null); expect(inst.count, null); @@ -968,17 +996,17 @@ void runTests({ test('Maps with null count and offset greater than 0 are ' 'truncated from offset to end of map', () async { - final map = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelMap', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - map.id!, - count: null, - offset: 1000, - ) as Instance; + final map = + await service.evaluate(isolate.id!, bootstrap!.id!, 'topLevelMap') + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + map.id!, + count: null, + offset: 1000, + ) + as Instance; expect(inst.length, 1001); expect(inst.offset, 1000); expect(inst.count, null); @@ -989,17 +1017,17 @@ void runTests({ }); test('Maps with null count are not truncated', () async { - final map = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelMap', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - map.id!, - count: null, - offset: 0, - ) as Instance; + final map = + await service.evaluate(isolate.id!, bootstrap!.id!, 'topLevelMap') + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + map.id!, + count: null, + offset: 0, + ) + as Instance; expect(inst.length, 1001); expect(inst.offset, 0); expect(inst.count, null); @@ -1013,17 +1041,12 @@ void runTests({ }); test('Maps with offset/count are truncated', () async { - final map = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelMap', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - map.id!, - count: 7, - offset: 4, - ) as Instance; + final map = + await service.evaluate(isolate.id!, bootstrap!.id!, 'topLevelMap') + as InstanceRef; + final inst = + await service.getObject(isolate.id!, map.id!, count: 7, offset: 4) + as Instance; expect(inst.length, 1001); expect(inst.offset, 4); expect(inst.count, 7); @@ -1039,17 +1062,21 @@ void runTests({ test( 'Maps are truncated to the end if offset/count runs off the end', () async { - final map = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelMap', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - map.id!, - count: 5, - offset: 1000, - ) as Instance; + final map = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelMap', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + map.id!, + count: 5, + offset: 1000, + ) + as Instance; expect(inst.length, 1001); expect(inst.offset, 1000); expect(inst.count, 1); @@ -1063,17 +1090,21 @@ void runTests({ test( 'Maps are truncated to empty if offset runs off the end', () async { - final map = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelMap', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - map.id!, - count: 5, - offset: 1002, - ) as Instance; + final map = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelMap', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + map.id!, + count: 5, + offset: 1002, + ) + as Instance; expect(inst.associations!.length, 0); expect(inst.length, 1001); expect(inst.offset, 1002); @@ -1083,17 +1114,21 @@ void runTests({ ); test('Strings with offset/count are truncated', () async { - final worldRef = await service.evaluate( - isolate.id!, - bootstrap!.id!, - "helloString('world')", - ) as InstanceRef; - final world = await service.getObject( - isolate.id!, - worldRef.id!, - count: 2, - offset: 1, - ) as Instance; + final worldRef = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + "helloString('world')", + ) + as InstanceRef; + final world = + await service.getObject( + isolate.id!, + worldRef.id!, + count: 2, + offset: 1, + ) + as Instance; expect(world.valueAsString, 'or'); expect(world.count, 2); expect(world.length, 5); @@ -1103,17 +1138,21 @@ void runTests({ test( 'Maps are truncated to empty if offset runs off the end', () async { - final map = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelMap', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - map.id!, - count: 5, - offset: 1002, - ) as Instance; + final map = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelMap', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + map.id!, + count: 5, + offset: 1002, + ) + as Instance; expect(inst.associations!.length, 0); expect(inst.length, 1001); expect(inst.offset, 1002); @@ -1125,17 +1164,21 @@ void runTests({ test( 'Maps are truncated to empty with 0 count and null offset', () async { - final map = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'topLevelMap', - ) as InstanceRef; - final inst = await service.getObject( - isolate.id!, - map.id!, - count: 0, - offset: null, - ) as Instance; + final map = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'topLevelMap', + ) + as InstanceRef; + final inst = + await service.getObject( + isolate.id!, + map.id!, + count: 0, + offset: null, + ) + as Instance; expect(inst.associations!.length, 0); expect(inst.length, 1001); expect(inst.offset, null); @@ -1147,17 +1190,21 @@ void runTests({ test( 'Strings are truncated to the end if offset/count runs off the end', () async { - final worldRef = await service.evaluate( - isolate.id!, - bootstrap!.id!, - "helloString('world')", - ) as InstanceRef; - final world = await service.getObject( - isolate.id!, - worldRef.id!, - count: 5, - offset: 3, - ) as Instance; + final worldRef = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + "helloString('world')", + ) + as InstanceRef; + final world = + await service.getObject( + isolate.id!, + worldRef.id!, + count: 5, + offset: 3, + ) + as Instance; expect(world.valueAsString, 'ld'); expect(world.count, 2); expect(world.length, 5); @@ -1168,12 +1215,14 @@ void runTests({ test( 'offset/count parameters greater than zero are ignored for Classes', () async { - final testClass = await service.getObject( - isolate.id!, - rootLibrary!.classes!.first.id!, - offset: 100, - count: 100, - ) as Class; + final testClass = + await service.getObject( + isolate.id!, + rootLibrary!.classes!.first.id!, + offset: 100, + count: 100, + ) + as Class; expect( testClass.functions, unorderedEquals([ @@ -1222,12 +1271,14 @@ void runTests({ test( 'offset/count parameters equal to zero are ignored for Classes', () async { - final testClass = await service.getObject( - isolate.id!, - rootLibrary!.classes!.first.id!, - offset: 0, - count: 0, - ) as Class; + final testClass = + await service.getObject( + isolate.id!, + rootLibrary!.classes!.first.id!, + offset: 0, + count: 0, + ) + as Class; expect( testClass.functions, unorderedEquals([ @@ -1274,51 +1325,63 @@ void runTests({ ); test('offset/count parameters are ignored for bools', () async { - final ref = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'helloBool(true)', - ) as InstanceRef; - final obj = await service.getObject( - isolate.id!, - ref.id!, - offset: 100, - count: 100, - ) as Instance; + final ref = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'helloBool(true)', + ) + as InstanceRef; + final obj = + await service.getObject( + isolate.id!, + ref.id!, + offset: 100, + count: 100, + ) + as Instance; expect(obj.kind, InstanceKind.kBool); expect(obj.classRef!.name, 'Bool'); expect(obj.valueAsString, 'true'); }); test('offset/count parameters are ignored for nums', () async { - final ref = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'helloNum(42)', - ) as InstanceRef; - final obj = await service.getObject( - isolate.id!, - ref.id!, - offset: 100, - count: 100, - ) as Instance; + final ref = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'helloNum(42)', + ) + as InstanceRef; + final obj = + await service.getObject( + isolate.id!, + ref.id!, + offset: 100, + count: 100, + ) + as Instance; expect(obj.kind, InstanceKind.kDouble); expect(obj.classRef!.name, 'Double'); expect(obj.valueAsString, '42'); }); test('offset/count parameters are ignored for null', () async { - final ref = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'helloNum(null)', - ) as InstanceRef; - final obj = await service.getObject( - isolate.id!, - ref.id!, - offset: 100, - count: 100, - ) as Instance; + final ref = + await service.evaluate( + isolate.id!, + bootstrap!.id!, + 'helloNum(null)', + ) + as InstanceRef; + final obj = + await service.getObject( + isolate.id!, + ref.id!, + offset: 100, + count: 100, + ) + as Instance; expect(obj.kind, InstanceKind.kNull); expect(obj.classRef!.name, 'Null'); expect(obj.valueAsString, 'null'); @@ -1678,8 +1741,9 @@ void runTests({ }); test('break on exceptions with setIsolatePauseMode', () async { - final oldPauseMode = (await service.getIsolate(isolateId!)) - .exceptionPauseMode; + final oldPauseMode = (await service.getIsolate( + isolateId!, + )).exceptionPauseMode; await service.setIsolatePauseMode( isolateId!, exceptionPauseMode: ExceptionPauseMode.kAll, @@ -1747,11 +1811,9 @@ void runTests({ vm = await service.getVM(); isolate = await service.getIsolate(vm.isolates!.first.id!); bootstrap = isolate.rootLib; - testInstance = await service.evaluate( - isolate.id!, - bootstrap!.id!, - 'myInstance', - ) as InstanceRef; + testInstance = + await service.evaluate(isolate.id!, bootstrap!.id!, 'myInstance') + as InstanceRef; }); test('rootLib', () async { @@ -2014,14 +2076,12 @@ void runTests({ final vm = await service.getVM(); final isolateId = vm.isolates!.first.id!; - final resolvedUris = await service.lookupResolvedPackageUris( - isolateId, - [ - 'package:does/not/exist.dart', - 'dart:does_not_exist', - 'file:///does_not_exist.dart', - ], - ); + final resolvedUris = await service + .lookupResolvedPackageUris(isolateId, [ + 'package:does/not/exist.dart', + 'dart:does_not_exist', + 'file:///does_not_exist.dart', + ]); expect(resolvedUris.uris, [null, null, null]); }, ); @@ -2517,8 +2577,9 @@ void runTests({ predicate( (Event event) => event.kind == EventKind.kWriteEvent && - String.fromCharCodes(base64.decode(event.bytes!)) - .contains('hello'), + String.fromCharCodes( + base64.decode(event.bytes!), + ).contains('hello'), ), ), ); @@ -2534,8 +2595,9 @@ void runTests({ predicate( (Event event) => event.kind == EventKind.kWriteEvent && - String.fromCharCodes(base64.decode(event.bytes!)) - .contains('Error'), + String.fromCharCodes( + base64.decode(event.bytes!), + ).contains('Error'), ), ), ); @@ -2551,8 +2613,9 @@ void runTests({ predicate( (Event event) => event.kind == EventKind.kWriteEvent && - String.fromCharCodes(base64.decode(event.bytes!)) - .contains('main.dart'), + String.fromCharCodes( + base64.decode(event.bytes!), + ).contains('main.dart'), ), ), ); diff --git a/dwds/test/integration/instances/common/class_inspection_common.dart b/dwds_test_common/lib/integration/class_inspection.dart similarity index 89% rename from dwds/test/integration/instances/common/class_inspection_common.dart rename to dwds_test_common/lib/integration/class_inspection.dart index da77bcc776..ba9bb612cc 100644 --- a/dwds/test/integration/instances/common/class_inspection_common.dart +++ b/dwds_test_common/lib/integration/class_inspection.dart @@ -7,22 +7,21 @@ @Timeout(Duration(minutes: 2)) library; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/integration/test_inspector.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../../fixtures/context.dart'; -import '../../fixtures/project.dart'; -import '../../fixtures/utilities.dart'; -import '../common/test_inspector.dart'; - void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { - final context = TestContext(TestProject.testExperiment, provider); + final context = contextFactory(TestProject.testExperiment, provider); final testInspector = TestInspector(context); late VmService service; @@ -44,12 +43,11 @@ void runTests({ Future getObject(String instanceId) => service.getObject(isolateId, instanceId); - group('$compilationMode |', () { + group('${context.runtimeType} |', () { setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, verboseCompiler: provider.verbose, experiments: ['dot-shorthands'], diff --git a/dwds_test_common/lib/integration/dart_uri_file_uri.dart b/dwds_test_common/lib/integration/dart_uri_file_uri.dart new file mode 100644 index 0000000000..dd00b126d8 --- /dev/null +++ b/dwds_test_common/lib/integration/dart_uri_file_uri.dart @@ -0,0 +1,81 @@ +// Copyright (c) 2026, 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:dwds/src/utilities/dart_uri.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +import '../fixtures/context.dart'; + +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final testProject = TestProject.test; + final testPackageProject = TestProject.testPackage(); + final context = contextFactory(testPackageProject, provider); + + group('Debugger module names: false |', () { + const useDebuggerModuleNames = false; + + final appServerPath = context.usesFrontendServer + ? 'web/main.dart' + : 'main.dart'; + final serverPath = + 'packages/${testPackageProject.packageName}/test_library.dart'; + final anotherServerPath = + 'packages/${testProject.packageName}/library.dart'; + + setUpAll(() async { + await context.setUp( + testSettings: TestSettings( + canaryFeatures: provider.canaryFeatures, + moduleFormat: provider.ddcModuleFormat, + useDebuggerModuleNames: useDebuggerModuleNames, + ), + ); + }); + + tearDownAll(() async { + await context.tearDown(); + }); + + test('file path to org-dartlang-app', () { + final webMain = Uri.file( + p.join(testPackageProject.absolutePackageDirectory, 'web', 'main.dart'), + ); + final uri = DartUri('$webMain'); + expect(uri.serverPath, appServerPath); + }); + + test('file path to this package', () { + final testPackageLib = Uri.file( + p.join( + testPackageProject.absolutePackageDirectory, + 'lib', + 'test_library.dart', + ), + ); + final uri = DartUri('$testPackageLib'); + expect(uri.serverPath, serverPath); + }); + + test('file path to another package', () { + final testLib = Uri.file( + p.join( + testPackageProject.absolutePackageDirectory, + '..', + testProject.packageDirectory, + 'lib', + 'library.dart', + ), + ); + final dartUri = DartUri('$testLib'); + expect(dartUri.serverPath, anotherServerPath); + }); + }); +} diff --git a/dwds_test_common/lib/integration/dart_uri_file_uri_debugger_module_names.dart b/dwds_test_common/lib/integration/dart_uri_file_uri_debugger_module_names.dart new file mode 100644 index 0000000000..ec9b3264d6 --- /dev/null +++ b/dwds_test_common/lib/integration/dart_uri_file_uri_debugger_module_names.dart @@ -0,0 +1,81 @@ +// Copyright (c) 2026, 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:dwds/src/utilities/dart_uri.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +import '../fixtures/context.dart'; + +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final testProject = TestProject.test; + final testPackageProject = TestProject.testPackage(); + final context = contextFactory(testPackageProject, provider); + + group('Debugger module names: true |', () { + const useDebuggerModuleNames = true; + + final appServerPath = context.usesFrontendServer + ? 'web/main.dart' + : 'main.dart'; + final serverPath = + 'packages/${testPackageProject.packageDirectory}/lib/test_library.dart'; + final anotherServerPath = + 'packages/${testProject.packageDirectory}/lib/library.dart'; + + setUpAll(() async { + await context.setUp( + testSettings: TestSettings( + canaryFeatures: provider.canaryFeatures, + moduleFormat: provider.ddcModuleFormat, + useDebuggerModuleNames: useDebuggerModuleNames, + ), + ); + }); + + tearDownAll(() async { + await context.tearDown(); + }); + + test('file path to org-dartlang-app', () { + final webMain = Uri.file( + p.join(testPackageProject.absolutePackageDirectory, 'web', 'main.dart'), + ); + final uri = DartUri('$webMain'); + expect(uri.serverPath, appServerPath); + }); + + test('file path to this package', () { + final testPackageLib = Uri.file( + p.join( + testPackageProject.absolutePackageDirectory, + 'lib', + 'test_library.dart', + ), + ); + final uri = DartUri('$testPackageLib'); + expect(uri.serverPath, serverPath); + }); + + test('file path to another package', () { + final testLib = Uri.file( + p.join( + testPackageProject.absolutePackageDirectory, + '..', + testProject.packageDirectory, + 'lib', + 'library.dart', + ), + ); + final dartUri = DartUri('$testLib'); + expect(dartUri.serverPath, anotherServerPath); + }); + }); +} diff --git a/dwds/test/integration/dds_port_common.dart b/dwds_test_common/lib/integration/dds_port.dart similarity index 85% rename from dwds/test/integration/dds_port_common.dart rename to dwds_test_common/lib/integration/dds_port.dart index 480f4e2024..6361f5c4bf 100644 --- a/dwds/test/integration/dds_port_common.dart +++ b/dwds_test_common/lib/integration/dds_port.dart @@ -5,20 +5,22 @@ import 'dart:io'; import 'package:dwds/dwds.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - -void testAll({required TestSdkConfigurationProvider provider}) { +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { late TestContext context; setUp(() { setCurrentLogWriter(debug: provider.verbose); - context = TestContext(TestProject.test, provider); + context = contextFactory(TestProject.test, provider); }); tearDown(() async { diff --git a/dwds/test/integration/debug_service_common.dart b/dwds_test_common/lib/integration/debug_service.dart similarity index 81% rename from dwds/test/integration/debug_service_common.dart rename to dwds_test_common/lib/integration/debug_service.dart index 1dd3cce050..2cf62dc5f4 100644 --- a/dwds/test/integration/debug_service_common.dart +++ b/dwds_test_common/lib/integration/debug_service.dart @@ -5,17 +5,19 @@ import 'dart:io'; import 'package:dwds/dwds.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:vm_service/vm_service_io.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - -void testAll({required TestSdkConfigurationProvider provider}) { - final context = TestContext(TestProject.test, provider); +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final context = contextFactory(TestProject.test, provider); setUpAll(() async { // Disable DDS as we're testing DWDS behavior. @@ -47,8 +49,9 @@ void testAll({required TestSdkConfigurationProvider provider}) { test('Accepts connections with the auth token', () async { expect( - vmServiceConnectUri('${context.debugConnection.uri}/ws') - .then((client) => client.dispose()), + vmServiceConnectUri( + '${context.debugConnection.uri}/ws', + ).then((client) => client.dispose()), completes, ); }); @@ -72,8 +75,9 @@ void testAll({required TestSdkConfigurationProvider provider}) { // However, once DDS is disconnected, additional clients can connect again. await fakeDds.dispose(); expect( - vmServiceConnectUri('${context.debugConnection.uri}/ws') - .then((client) => client.dispose()), + vmServiceConnectUri( + '${context.debugConnection.uri}/ws', + ).then((client) => client.dispose()), completes, ); }); diff --git a/dwds/test/integration/devtools_common.dart b/dwds_test_common/lib/integration/devtools.dart similarity index 95% rename from dwds/test/integration/devtools_common.dart rename to dwds_test_common/lib/integration/devtools.dart index 8d8a4e6def..6bb174f4b0 100644 --- a/dwds/test/integration/devtools_common.dart +++ b/dwds_test_common/lib/integration/devtools.dart @@ -5,16 +5,15 @@ import 'dart:io'; import 'package:dwds/src/config/tool_configuration.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; // ignore: deprecated_member_use import 'package:webdriver/io.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - Future _waitForPageReady(TestContext context) async { var attempt = 100; while (attempt-- > 0) { @@ -28,8 +27,11 @@ Future _waitForPageReady(TestContext context) async { TypeMatcher _hasKind(String kind) => isA().having((Event e) => e.kind, 'kind', kind); -void testAll({required TestSdkConfigurationProvider provider}) { - final context = TestContext(TestProject.test, provider); +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final context = contextFactory(TestProject.test, provider); for (final serveFromDds in [true, false]) { group('Injected client with DevTools served from ' diff --git a/dwds/test/integration/instances/common/dot_shorthands_common.dart b/dwds_test_common/lib/integration/dot_shorthands.dart similarity index 91% rename from dwds/test/integration/instances/common/dot_shorthands_common.dart rename to dwds_test_common/lib/integration/dot_shorthands.dart index f37bd6f7f8..b6cb6f03b4 100644 --- a/dwds/test/integration/instances/common/dot_shorthands_common.dart +++ b/dwds_test_common/lib/integration/dot_shorthands.dart @@ -2,23 +2,22 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/integration/test_inspector.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:path/path.dart' show basename; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../../fixtures/context.dart'; -import '../../fixtures/project.dart'; -import '../../fixtures/utilities.dart'; -import 'test_inspector.dart'; - void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { - final context = TestContext(TestProject.testDotShorthands, provider); + final context = contextFactory(TestProject.testDotShorthands, provider); final testInspector = TestInspector(context); late VmService service; @@ -40,12 +39,11 @@ void runTests({ Future getInstanceRef(int frame, String expression) => testInspector.getInstanceRef(isolateId, frame, expression); - group('$compilationMode | dot shorthands:', () { + group('${context.runtimeType} | dot shorthands:', () { setUp(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, verboseCompiler: provider.verbose, experiments: ['dot-shorthands'], diff --git a/dwds/test/integration/evaluate_common.dart b/dwds_test_common/lib/integration/evaluate.dart similarity index 98% rename from dwds/test/integration/evaluate_common.dart rename to dwds_test_common/lib/integration/evaluate.dart index 3e3f8b51c4..325fa7abbb 100644 --- a/dwds/test/integration/evaluate_common.dart +++ b/dwds_test_common/lib/integration/evaluate.dart @@ -9,6 +9,9 @@ library; import 'dart:async'; import 'package:dwds/src/services/expression_evaluator.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:dwds_test_common/utilities.dart' show dartSdkIsAtLeast; @@ -16,28 +19,23 @@ import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - void testAll({ required TestSdkConfigurationProvider provider, - CompilationMode compilationMode = CompilationMode.buildDaemon, + required TestContextFactory contextFactory, IndexBaseMode indexBaseMode = IndexBaseMode.noBase, bool useDebuggerModuleNames = false, }) { - if (compilationMode == CompilationMode.buildDaemon && - indexBaseMode == IndexBaseMode.base) { + final testProject = TestProject.test; + final testPackageProject = TestProject.testPackage(baseMode: indexBaseMode); + + final context = contextFactory(testPackageProject, provider); + + if (context.usesBuildDaemon && indexBaseMode == IndexBaseMode.base) { throw StateError( 'build daemon scenario does not support non-empty base in index file', ); } - final testProject = TestProject.test; - final testPackageProject = TestProject.testPackage(baseMode: indexBaseMode); - - final context = TestContext(testPackageProject, provider); - Future onBp( Stream stream, String isolate, @@ -74,7 +72,6 @@ void testAll({ setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, enableExpressionEvaluation: true, useDebuggerModuleNames: useDebuggerModuleNames, @@ -825,7 +822,6 @@ void testAll({ setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, enableExpressionEvaluation: false, verboseCompiler: provider.verbose, diff --git a/dwds/test/integration/evaluate_circular_common.dart b/dwds_test_common/lib/integration/evaluate_circular.dart similarity index 92% rename from dwds/test/integration/evaluate_circular_common.dart rename to dwds_test_common/lib/integration/evaluate_circular.dart index 8aa570008c..59e3a2d5f4 100644 --- a/dwds/test/integration/evaluate_circular_common.dart +++ b/dwds_test_common/lib/integration/evaluate_circular.dart @@ -6,34 +6,32 @@ @Timeout(Duration(minutes: 2)) library; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:vm_service_interface/vm_service_interface.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - void testAll({ required TestSdkConfigurationProvider provider, - CompilationMode compilationMode = CompilationMode.buildDaemon, + required TestContextFactory contextFactory, IndexBaseMode indexBaseMode = IndexBaseMode.noBase, bool useDebuggerModuleNames = false, }) { - if (compilationMode == CompilationMode.buildDaemon && - indexBaseMode == IndexBaseMode.base) { + final testCircular1 = TestProject.testCircular1; + final testCircular2 = TestProject.testCircular2(baseMode: indexBaseMode); + + final context = contextFactory(testCircular2, provider); + + if (context.usesBuildDaemon && indexBaseMode == IndexBaseMode.base) { throw StateError( 'build daemon scenario does not support non-empty base in index file', ); } - final testCircular1 = TestProject.testCircular1; - final testCircular2 = TestProject.testCircular2(baseMode: indexBaseMode); - - final context = TestContext(testCircular2, provider); - Future onBreakPoint( String isolate, ScriptRef script, @@ -66,7 +64,6 @@ void testAll({ setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, useDebuggerModuleNames: useDebuggerModuleNames, verboseCompiler: provider.verbose, diff --git a/dwds/test/integration/evaluate_parts_common.dart b/dwds_test_common/lib/integration/evaluate_parts.dart similarity index 93% rename from dwds/test/integration/evaluate_parts_common.dart rename to dwds_test_common/lib/integration/evaluate_parts.dart index 21c6155435..ac8eadd969 100644 --- a/dwds/test/integration/evaluate_parts_common.dart +++ b/dwds_test_common/lib/integration/evaluate_parts.dart @@ -2,33 +2,31 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:vm_service_interface/vm_service_interface.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - void testAll({ required TestSdkConfigurationProvider provider, - CompilationMode compilationMode = CompilationMode.buildDaemon, + required TestContextFactory contextFactory, IndexBaseMode indexBaseMode = IndexBaseMode.noBase, bool useDebuggerModuleNames = false, }) { - if (compilationMode == CompilationMode.buildDaemon && - indexBaseMode == IndexBaseMode.base) { + final testParts = TestProject.testParts(baseMode: indexBaseMode); + + final context = contextFactory(testParts, provider); + + if (context.usesBuildDaemon && indexBaseMode == IndexBaseMode.base) { throw StateError( 'build daemon scenario does not support non-empty base in index file', ); } - final testParts = TestProject.testParts(baseMode: indexBaseMode); - - final context = TestContext(testParts, provider); - Future onBreakPoint( String isolate, ScriptRef script, @@ -69,7 +67,6 @@ void testAll({ setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, useDebuggerModuleNames: useDebuggerModuleNames, verboseCompiler: provider.verbose, diff --git a/dwds/test/integration/events_common.dart b/dwds_test_common/lib/integration/events.dart similarity index 98% rename from dwds/test/integration/events_common.dart rename to dwds_test_common/lib/integration/events.dart index c8e050d12c..e2d8b869e2 100644 --- a/dwds/test/integration/events_common.dart +++ b/dwds_test_common/lib/integration/events.dart @@ -6,6 +6,9 @@ import 'dart:async'; import 'dart:io'; import 'package:dwds/src/events.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; @@ -13,15 +16,11 @@ import 'package:vm_service/vm_service.dart'; import 'package:vm_service_interface/vm_service_interface.dart'; import 'package:webdriver/async_core.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - void testWithDwds({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, }) { - final context = TestContext(TestProject.test, provider); + final context = contextFactory(TestProject.test, provider); group( 'with dwds', @@ -73,7 +72,7 @@ void testWithDwds({ pipe(eventStream, timeout: const Timeout.factor(5)), emitsThrough( matchesEvent(DwdsEventKind.compilerUpdateDependencies, { - if (compilationMode == CompilationMode.frontendServer) + if (context.usesFrontendServer) 'entrypoint': 'example/hello_world/main_module.bootstrap.js' else 'entrypoint': 'hello_world/main.dart.bootstrap.js', @@ -83,7 +82,6 @@ void testWithDwds({ ); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, moduleFormat: provider.ddcModuleFormat, verboseCompiler: provider.verbose, diff --git a/dwds/test/integration/expression_compiler_service_common.dart b/dwds_test_common/lib/integration/expression_compiler_service.dart similarity index 100% rename from dwds/test/integration/expression_compiler_service_common.dart rename to dwds_test_common/lib/integration/expression_compiler_service.dart diff --git a/dwds/test/integration/hot_reload_common.dart b/dwds_test_common/lib/integration/hot_reload.dart similarity index 93% rename from dwds/test/integration/hot_reload_common.dart rename to dwds_test_common/lib/integration/hot_reload.dart index ebb780ea52..bcb8c17d69 100644 --- a/dwds/test/integration/hot_reload_common.dart +++ b/dwds_test_common/lib/integration/hot_reload.dart @@ -4,24 +4,23 @@ import 'dart:async'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - const originalString = 'Hello World!'; const newString = 'Bonjour le monde!'; void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, }) { final project = TestProject.testHotReload; - final context = TestContext(project, provider); + final context = contextFactory(project, provider); Future recompile() async { await context.recompile(fullRestart: false); @@ -71,7 +70,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( enableExpressionEvaluation: true, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), diff --git a/dwds/test/integration/hot_reload_breakpoints_common.dart b/dwds_test_common/lib/integration/hot_reload_breakpoints.dart similarity index 98% rename from dwds/test/integration/hot_reload_breakpoints_common.dart rename to dwds_test_common/lib/integration/hot_reload_breakpoints.dart index 276781b3ab..fdd7799432 100644 --- a/dwds/test/integration/hot_reload_breakpoints_common.dart +++ b/dwds_test_common/lib/integration/hot_reload_breakpoints.dart @@ -4,21 +4,20 @@ import 'dart:async'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, }) { final project = TestProject.testHotReloadBreakpoints; - final context = TestContext(project, provider); + final context = contextFactory(project, provider); final mainFile = project.dartEntryFileName; final callLogMarker = 'callLog'; final capturedStringMarker = 'capturedString'; @@ -37,7 +36,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( enableExpressionEvaluation: true, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -521,7 +519,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( enableExpressionEvaluation: true, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), diff --git a/dwds/test/integration/common/hot_restart_common.dart b/dwds_test_common/lib/integration/hot_restart.dart similarity index 95% rename from dwds/test/integration/common/hot_restart_common.dart rename to dwds_test_common/lib/integration/hot_restart.dart index 9d0dff7c23..80beb7ef3f 100644 --- a/dwds/test/integration/common/hot_restart_common.dart +++ b/dwds_test_common/lib/integration/hot_restart.dart @@ -11,33 +11,32 @@ import 'dart:async'; import 'package:dwds/dwds.dart'; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../fixtures/context.dart'; -import '../fixtures/project.dart'; -import '../fixtures/utilities.dart'; - const originalString = 'Hello World!'; const newString = 'Bonjour le monde!'; void runTests({ required TestSdkConfigurationProvider provider, required ModuleFormat moduleFormat, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { - final context = TestContext(TestProject.testAppendBody, provider); + final context = contextFactory(TestProject.testAppendBody, provider); tearDownAll(provider.dispose); Future recompile({bool hasEdits = false}) async { - if (compilationMode == CompilationMode.frontendServer) { + if (context.usesFrontendServer) { await context.recompile(fullRestart: true); } else { - assert(compilationMode == CompilationMode.buildDaemon); + assert(context.usesBuildDaemon); if (hasEdits) { // Only gets a new build if there were edits. await context.waitForSuccessfulBuild(); @@ -89,7 +88,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( reloadConfiguration: ReloadConfiguration.liveReload, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -114,7 +112,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( reloadConfiguration: ReloadConfiguration.liveReload, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -142,7 +139,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( reloadConfiguration: ReloadConfiguration.liveReload, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -166,7 +162,7 @@ void runTests({ }); }, // `BuildResult`s are only ever emitted when using the build daemon. - skip: compilationMode == CompilationMode.buildDaemon ? null : true, + skip: context.usesBuildDaemon ? null : true, timeout: const Timeout.factor(2), ); @@ -178,7 +174,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( enableExpressionEvaluation: true, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -319,8 +314,9 @@ void runTests({ final eventsDone = expectLater( client.onIsolateEvent, emitsThrough( - _hasKind(EventKind.kServiceExtensionAdded) - .having((e) => e.extensionRPC, 'service', 'ext.bar'), + _hasKind( + EventKind.kServiceExtensionAdded, + ).having((e) => e.extensionRPC, 'service', 'ext.bar'), ), ); @@ -481,7 +477,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( reloadConfiguration: ReloadConfiguration.hotRestart, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -534,7 +529,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( reloadConfiguration: ReloadConfiguration.hotRestart, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -562,7 +556,7 @@ void runTests({ }); }, // `BuildResult`s are only ever emitted when using the build daemon. - skip: compilationMode == CompilationMode.buildDaemon ? null : true, + skip: context.usesBuildDaemon ? null : true, timeout: const Timeout.factor(2), ); @@ -575,7 +569,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( enableExpressionEvaluation: true, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), diff --git a/dwds/test/integration/hot_restart_breakpoints_common.dart b/dwds_test_common/lib/integration/hot_restart_breakpoints.dart similarity index 93% rename from dwds/test/integration/hot_restart_breakpoints_common.dart rename to dwds_test_common/lib/integration/hot_restart_breakpoints.dart index e9991c5497..096bb53a9d 100644 --- a/dwds/test/integration/hot_restart_breakpoints_common.dart +++ b/dwds_test_common/lib/integration/hot_restart_breakpoints.dart @@ -4,7 +4,9 @@ import 'dart:async'; -import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; @@ -12,45 +14,18 @@ import 'package:vm_service/vm_service.dart'; import 'package:vm_service_interface/vm_service_interface.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - -void main() { - // Enable verbose logging for debugging. - const debug = false; - final provider = TestSdkConfigurationProvider( - verbose: debug, - canaryFeatures: true, - ddcModuleFormat: ModuleFormat.ddc, - ); - - tearDownAll(provider.dispose); - - group('Frontend Server', () { - runTests( - provider: provider, - compilationMode: CompilationMode.frontendServer, - ); - }); - - group('Build Daemon', () { - runTests(provider: provider, compilationMode: CompilationMode.buildDaemon); - }); -} - void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, }) { final project = TestProject.testHotRestartBreakpoints; - final context = TestContext(project, provider); + final context = contextFactory(project, provider); final mainFile = project.dartEntryFileName; final callLogMarker = 'callLog'; Future makeEditsAndRecompile(List edits) async { await context.makeEdits(edits); - if (compilationMode == CompilationMode.frontendServer) { + if (context.usesFrontendServer) { await context.recompile(fullRestart: true); } else { await context.waitForSuccessfulBuild(); @@ -70,7 +45,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( enableExpressionEvaluation: true, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -215,7 +189,7 @@ void runTests({ final breakpointFuture = waitForBreakpoint(); - if (compilationMode == CompilationMode.frontendServer) { + if (context.usesFrontendServer) { await context.recompile(fullRestart: false); } diff --git a/dwds/test/integration/common/hot_restart_correctness_common.dart b/dwds_test_common/lib/integration/hot_restart_correctness.dart similarity index 91% rename from dwds/test/integration/common/hot_restart_correctness_common.dart rename to dwds_test_common/lib/integration/hot_restart_correctness.dart index dc37269678..889f427c13 100644 --- a/dwds/test/integration/common/hot_restart_correctness_common.dart +++ b/dwds_test_common/lib/integration/hot_restart_correctness.dart @@ -11,15 +11,14 @@ import 'dart:async'; import 'package:dwds/dwds.dart'; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../fixtures/context.dart'; -import '../fixtures/project.dart'; -import '../fixtures/utilities.dart'; - const originalString = 'variableToModifyToForceRecompile = 23'; const newString = 'variableToModifyToForceRecompile = 45'; @@ -29,13 +28,13 @@ const constantFailureString = 'ConstantEqualityFailure'; void runTests({ required TestSdkConfigurationProvider provider, required ModuleFormat moduleFormat, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { tearDownAll(provider.dispose); final testHotRestart2 = TestProject.testHotRestart2; - final context = TestContext(testHotRestart2, provider); + final context = contextFactory(testHotRestart2, provider); Future makeEditAndRecompile() async { await context.makeEdits([ @@ -45,10 +44,10 @@ void runTests({ newString: newString, ), ]); - if (compilationMode == CompilationMode.frontendServer) { + if (context.usesFrontendServer) { await context.recompile(fullRestart: true); } else { - assert(compilationMode == CompilationMode.buildDaemon); + assert(context.usesBuildDaemon); await context.waitForSuccessfulBuild(propagateToBrowser: true); } } @@ -80,7 +79,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( enableExpressionEvaluation: true, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -149,7 +147,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( reloadConfiguration: ReloadConfiguration.hotRestart, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -175,7 +172,6 @@ void runTests({ await context.setUp( testSettings: TestSettings( reloadConfiguration: ReloadConfiguration.hotRestart, - compilationMode: compilationMode, moduleFormat: provider.ddcModuleFormat, canaryFeatures: provider.canaryFeatures, ), @@ -199,7 +195,7 @@ void runTests({ }); }, // `BuildResult`s are only ever emitted when using the build daemon. - skip: compilationMode == CompilationMode.buildDaemon ? null : true, + skip: context.usesBuildDaemon ? null : true, timeout: const Timeout.factor(2), ); } diff --git a/dwds/test/integration/inspector_test.dart b/dwds_test_common/lib/integration/inspector.dart similarity index 84% rename from dwds/test/integration/inspector_test.dart rename to dwds_test_common/lib/integration/inspector.dart index 0a305b9421..7cf06dd391 100644 --- a/dwds/test/integration/inspector_test.dart +++ b/dwds_test_common/lib/integration/inspector.dart @@ -2,32 +2,33 @@ // 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') -@Timeout(Duration(minutes: 2)) -library; - import 'package:dwds/dwds.dart'; -import 'package:dwds/src/config/tool_configuration.dart'; +import 'package:dwds/expression_compiler.dart'; import 'package:dwds/src/debugging/chrome_inspector.dart'; import 'package:dwds/src/utilities/conversions.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; - -void main() { - final provider = TestSdkConfigurationProvider(); - tearDownAll(provider.dispose); - - final context = TestContext(TestProject.testScopes, provider); +void runTests({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final context = contextFactory(TestProject.testScopes, provider); late ChromeAppInspector inspector; setUpAll(() async { - await context.setUp(); + await context.setUp( + testSettings: TestSettings( + moduleFormat: provider.ddcModuleFormat, + canaryFeatures: provider.canaryFeatures, + ), + ); final service = context.service; inspector = service.inspector; }); @@ -38,15 +39,11 @@ void main() { final url = 'org-dartlang-app:///example/scopes/main.dart'; - /// A convenient way to get a library variable without boilerplate. - String libraryVariableExpression(String variable) => - '${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").dart.getModuleLibraries("example/scopes/main")["$url"]["$variable"];'; - Future libraryPublicFinal() => - inspector.jsEvaluate(libraryVariableExpression('libraryPublicFinal')); + inspector.invoke(url, 'getLibraryPublicFinal'); Future libraryPrivate() => - inspector.jsEvaluate(libraryVariableExpression('_libraryPrivate')); + inspector.invoke(url, 'getLibraryPrivate'); group('jsEvaluate', () { test('no error', () async { @@ -103,26 +100,32 @@ void main() { }); group('mapExceptionStackTrace', () { + final skipFrontendServerAmd = + context.usesFrontendServer && + provider.ddcModuleFormat == ModuleFormat.amd + ? 'Stack trace mapping not supported in this configuration' + : null; + test('multi-line exception with a stack trace', () async { final result = await inspector.mapExceptionStackTrace( jsMultiLineExceptionWithStackTrace, ); expect(result, equals(formattedMultiLineExceptionWithStackTrace)); - }); + }, skip: skipFrontendServerAmd); test('multi-line exception without a stack trace', () async { final result = await inspector.mapExceptionStackTrace( jsMultiLineExceptionNoStackTrace, ); expect(result, equals(formattedMultiLineExceptionNoStackTrace)); - }); + }, skip: skipFrontendServerAmd); test('single-line exception with a stack trace', () async { final result = await inspector.mapExceptionStackTrace( jsSingleLineExceptionWithStackTrace, ); - expect(result, equals(formattedSingleLineExceptionWithStackTrace)); - }); + expect(result, matches(formattedSingleLineExceptionWithStackTrace)); + }, skip: skipFrontendServerAmd); }); test('send toString', () async { @@ -166,10 +169,10 @@ void main() { test('properties', () async { final remoteObject = await libraryPublicFinal(); final properties = await inspector.getProperties(remoteObject.objectId!); - final names = properties - .map((p) => p.name) - .where((x) => x != '__proto__') - .toList(); + final names = + properties.map((p) => p.name).where((x) => x != '__proto__').toList() + ..removeWhere((name) => name == r'$ti'); + names.sort(); final expected = [ '_privateField', 'abstractField', @@ -181,7 +184,6 @@ void main() { 'tornOff', 'unchangedCount', ]; - names.sort(); expect(names, expected); }); @@ -321,10 +323,10 @@ Error: Unexpected null value. at http://localhost:63236/web_entrypoint.dart.lib.js:41:33 '''; -final formattedSingleLineExceptionWithStackTrace = ''' -Error: Unexpected null value. -http://localhost:63236/dart_sdk.js 5379:11 throw_ -http://localhost:63236/dart_sdk.js 5696:30 nullCheck -http://localhost:63236/packages/tmpapp/main.dart.lib.js 374:10 main -http://localhost:63236/web_entrypoint.dart.lib.js 41:33 -'''; +final formattedSingleLineExceptionWithStackTrace = RegExp( + r'^Error: Unexpected null value\.\n' + r'(?:http://localhost:\d+/dart_sdk\.js|dart:sdk_internal) 5379:11\s+throw_\n' + r'(?:http://localhost:\d+/dart_sdk\.js|dart:sdk_internal) 5696:30\s+nullCheck\n' + r'http://localhost:\d+/packages/tmpapp/main\.dart\.lib\.js 374:10\s+main\n' + r'http://localhost:\d+/web_entrypoint\.dart\.lib\.js 41:33\s+\n$', +); diff --git a/dwds/test/integration/instances/common/instance_common.dart b/dwds_test_common/lib/integration/instance.dart similarity index 95% rename from dwds/test/integration/instances/common/instance_common.dart rename to dwds_test_common/lib/integration/instance.dart index 492c49badf..8fa5a33287 100644 --- a/dwds/test/integration/instances/common/instance_common.dart +++ b/dwds_test_common/lib/integration/instance.dart @@ -5,39 +5,37 @@ import 'package:dwds/expression_compiler.dart'; import 'package:dwds/src/config/tool_configuration.dart'; import 'package:dwds/src/debugging/chrome_inspector.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/integration/test_inspector.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; -import '../../fixtures/context.dart'; -import '../../fixtures/project.dart'; -import '../../fixtures/utilities.dart'; -import 'test_inspector.dart'; - void runTypeSystemVerificationTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { final project = TestProject.testScopes; + final context = contextFactory(project, provider); - group('$compilationMode |', () { - final context = TestContext(project, provider); + group('${context.runtimeType} |', () { late ChromeAppInspector inspector; setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, verboseCompiler: provider.verbose, canaryFeatures: canaryFeatures, + moduleFormat: provider.ddcModuleFormat, ), ); - final chromeProxyService = context.service; - inspector = chromeProxyService.inspector; + inspector = context.service.inspector; }); tearDownAll(() async { @@ -46,19 +44,15 @@ void runTypeSystemVerificationTests({ final url = 'org-dartlang-app:///example/scopes/main.dart'; - String libraryName(CompilationMode compilationMode) => - compilationMode == CompilationMode.frontendServer + String libraryName() => context.usesFrontendServer ? 'example/scopes/main.dart' : 'example/scopes/main'; - String libraryVariableTypeExpression( - String variable, - CompilationMode compilationMode, - ) => + String libraryVariableTypeExpression(String variable) => ''' (function() { var dart = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk').dart; - var libraryName = '${libraryName(compilationMode)}'; + var libraryName = '${libraryName()}'; var library = dart.getModuleLibraries(libraryName)['$url']; var x = library['$variable']; return dart.getReifiedType(x); @@ -70,7 +64,7 @@ void runTypeSystemVerificationTests({ test('uses correct type system', () async { final remoteObject = await inspector.jsEvaluate( - libraryVariableTypeExpression('libraryPublicFinal', compilationMode), + libraryVariableTypeExpression('libraryPublicFinal'), ); expect(remoteObject.json['className'], 'dart_rti.Rti.new'); }); @@ -80,20 +74,19 @@ void runTypeSystemVerificationTests({ void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { final project = TestProject.testScopes; - final context = TestContext(project, provider); + final context = contextFactory(project, provider); late ChromeAppInspector inspector; - group('$compilationMode |', () { + group('${context.runtimeType} |', () { setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, verboseCompiler: provider.verbose, canaryFeatures: canaryFeatures, moduleFormat: provider.ddcModuleFormat, diff --git a/dwds/test/integration/instances/common/instance_inspection_common.dart b/dwds_test_common/lib/integration/instance_inspection.dart similarity index 96% rename from dwds/test/integration/instances/common/instance_inspection_common.dart rename to dwds_test_common/lib/integration/instance_inspection.dart index 13f91262f1..6fe0038216 100644 --- a/dwds/test/integration/instances/common/instance_inspection_common.dart +++ b/dwds_test_common/lib/integration/instance_inspection.dart @@ -2,23 +2,22 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/integration/test_inspector.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../../fixtures/context.dart'; -import '../../fixtures/project.dart'; -import '../../fixtures/utilities.dart'; -import 'test_inspector.dart'; - void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { final project = TestProject.testPackage(); - final context = TestContext(project, provider); + final context = contextFactory(project, provider); late VmService service; late Stream stream; @@ -58,12 +57,11 @@ void runTests({ count: count, ); - group('$compilationMode |', () { + group('${context.runtimeType} |', () { setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, verboseCompiler: provider.verbose, canaryFeatures: canaryFeatures, diff --git a/dwds/test/integration/listviews_test.dart b/dwds_test_common/lib/integration/listviews.dart similarity index 54% rename from dwds/test/integration/listviews_test.dart rename to dwds_test_common/lib/integration/listviews.dart index a9a63b1310..55ba7fbd40 100644 --- a/dwds/test/integration/listviews_test.dart +++ b/dwds_test_common/lib/integration/listviews.dart @@ -1,24 +1,29 @@ -// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2026, 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. -@Timeout(Duration(minutes: 2)) -library; - +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; - -void main() { - final provider = TestSdkConfigurationProvider(); - tearDownAll(provider.dispose); - - final context = TestContext(TestProject.test, provider); +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final context = contextFactory(TestProject.test, provider); setUpAll(() async { - await context.setUp(); + setCurrentLogWriter(debug: provider.verbose); + await context.setUp( + testSettings: TestSettings( + verboseCompiler: provider.verbose, + moduleFormat: provider.ddcModuleFormat, + canaryFeatures: provider.canaryFeatures, + ), + ); }); tearDownAll(() async { diff --git a/dwds/test/integration/load_strategy_test.dart b/dwds_test_common/lib/integration/load_strategy.dart similarity index 65% rename from dwds/test/integration/load_strategy_test.dart rename to dwds_test_common/lib/integration/load_strategy.dart index 6ca17eba9b..9cd87c4985 100644 --- a/dwds/test/integration/load_strategy_test.dart +++ b/dwds_test_common/lib/integration/load_strategy.dart @@ -1,31 +1,36 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2026, 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') -@Timeout(Duration(minutes: 1)) -library; - import 'package:dwds/dwds.dart'; import 'package:dwds/src/config/tool_configuration.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/fakes.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; -import 'fixtures/context.dart'; -import 'fixtures/fakes.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - -void main() { +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { group('Load Strategy', () { final project = TestProject.test; - final provider = TestSdkConfigurationProvider(); - tearDownAll(provider.dispose); - - final context = TestContext(project, provider); - - setUpAll(context.setUp); + final context = contextFactory(project, provider); + + setUpAll(() async { + setCurrentLogWriter(debug: provider.verbose); + await context.setUp( + testSettings: TestSettings( + verboseCompiler: provider.verbose, + moduleFormat: provider.ddcModuleFormat, + canaryFeatures: provider.canaryFeatures, + ), + ); + }); tearDownAll(context.tearDown); group( @@ -119,54 +124,48 @@ void main() { loadStrategy.buildSettings.appEntrypoint, project.dartEntryFilePackageUri, ); - expect(loadStrategy.buildSettings.canaryFeatures, isFalse); + expect( + loadStrategy.buildSettings.canaryFeatures, + provider.canaryFeatures, + ); expect(loadStrategy.buildSettings.isFlutterApp, isFalse); expect(loadStrategy.buildSettings.experiments, isEmpty); }); }); }); - group('Global load Strategy with custom build settings ', () { + group('Global load strategy with custom build settings', () { final canaryFeatures = true; final isFlutterApp = true; final experiments = ['records']; final project = TestProject.test; - final provider = TestSdkConfigurationProvider( - canaryFeatures: canaryFeatures, - ); - tearDownAll(provider.dispose); - - final context = TestContext(project, provider); - - for (final compilationMode in CompilationMode.values.where( - (mode) => !mode.usesDdcModulesOnly, - )) { - group('compiled with ${compilationMode.name}', () { - setUpAll(() async { - await context.setUp( - testSettings: TestSettings( - compilationMode: compilationMode, - canaryFeatures: canaryFeatures, - isFlutterApp: isFlutterApp, - experiments: experiments, - ), - ); - }); + final context = contextFactory(project, provider); + + setUpAll(() async { + setCurrentLogWriter(debug: provider.verbose); + await context.setUp( + testSettings: TestSettings( + canaryFeatures: canaryFeatures, + isFlutterApp: isFlutterApp, + experiments: experiments, + verboseCompiler: provider.verbose, + moduleFormat: provider.ddcModuleFormat, + ), + ); + }); - tearDownAll(context.tearDown); + tearDownAll(context.tearDown); - test('provides custom build settings', () { - final loadStrategy = globalToolConfiguration.loadStrategy; - expect( - loadStrategy.buildSettings.appEntrypoint, - project.dartEntryFilePackageUri, - ); - expect(loadStrategy.buildSettings.canaryFeatures, canaryFeatures); - expect(loadStrategy.buildSettings.isFlutterApp, isFlutterApp); - expect(loadStrategy.buildSettings.experiments, experiments); - }); - }); - } + test('provides custom build settings', () { + final loadStrategy = globalToolConfiguration.loadStrategy; + expect( + loadStrategy.buildSettings.appEntrypoint, + project.dartEntryFilePackageUri, + ); + expect(loadStrategy.buildSettings.canaryFeatures, canaryFeatures); + expect(loadStrategy.buildSettings.isFlutterApp, isFlutterApp); + expect(loadStrategy.buildSettings.experiments, experiments); + }); }); } diff --git a/dwds/test/integration/instances/common/patterns_inspection_common.dart b/dwds_test_common/lib/integration/patterns_inspection.dart similarity index 93% rename from dwds/test/integration/instances/common/patterns_inspection_common.dart rename to dwds_test_common/lib/integration/patterns_inspection.dart index 8255c56864..ccac5f16dd 100644 --- a/dwds/test/integration/instances/common/patterns_inspection_common.dart +++ b/dwds_test_common/lib/integration/patterns_inspection.dart @@ -2,22 +2,21 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/integration/test_inspector.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../../fixtures/context.dart'; -import '../../fixtures/project.dart'; -import '../../fixtures/utilities.dart'; -import 'test_inspector.dart'; - void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { - final context = TestContext(TestProject.testExperiment, provider); + final context = contextFactory(TestProject.testExperiment, provider); final testInspector = TestInspector(context); late VmService service; @@ -53,12 +52,11 @@ void runTests({ Future> getFrameVariables(Frame frame) => testInspector.getFrameVariables(isolateId, frame); - group('$compilationMode |', () { + group('${context.runtimeType} |', () { setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, verboseCompiler: provider.verbose, experiments: ['dot-shorthands'], diff --git a/dwds/test/integration/readers/proxy_server_asset_reader_common.dart b/dwds_test_common/lib/integration/readers/proxy_server_asset_reader.dart similarity index 82% rename from dwds/test/integration/readers/proxy_server_asset_reader_common.dart rename to dwds_test_common/lib/integration/readers/proxy_server_asset_reader.dart index b1b04f7930..ed844ba471 100644 --- a/dwds/test/integration/readers/proxy_server_asset_reader_common.dart +++ b/dwds_test_common/lib/integration/readers/proxy_server_asset_reader.dart @@ -3,16 +3,18 @@ // BSD-style license that can be found in the LICENSE file. import 'package:dwds/src/readers/proxy_server_asset_reader.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import '../fixtures/project.dart'; -import '../fixtures/utilities.dart'; - -void testAll({required TestSdkConfigurationProvider provider}) { +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { group('ProxyServerAssetReader', () { - final context = TestContext(TestProject.test, provider); + final context = contextFactory(TestProject.test, provider); late ProxyServerAssetReader assetReader; setUpAll(() async { diff --git a/dwds/test/integration/instances/common/record_inspection_common.dart b/dwds_test_common/lib/integration/record_inspection.dart similarity index 97% rename from dwds/test/integration/instances/common/record_inspection_common.dart rename to dwds_test_common/lib/integration/record_inspection.dart index ef4c65cd22..5e55fee944 100644 --- a/dwds/test/integration/instances/common/record_inspection_common.dart +++ b/dwds_test_common/lib/integration/record_inspection.dart @@ -2,22 +2,21 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/integration/test_inspector.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../../fixtures/context.dart'; -import '../../fixtures/project.dart'; -import '../../fixtures/utilities.dart'; -import 'test_inspector.dart'; - void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { - final context = TestContext(TestProject.testExperiment, provider); + final context = contextFactory(TestProject.testExperiment, provider); final testInspector = TestInspector(context); late VmService service; @@ -58,12 +57,11 @@ void runTests({ depth: depth, ); - group('$compilationMode |', () { + group('${context.runtimeType} |', () { setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, verboseCompiler: provider.verbose, experiments: ['dot-shorthands'], diff --git a/dwds/test/integration/instances/common/record_type_inspection_common.dart b/dwds_test_common/lib/integration/record_type_inspection.dart similarity index 97% rename from dwds/test/integration/instances/common/record_type_inspection_common.dart rename to dwds_test_common/lib/integration/record_type_inspection.dart index 82eb5c3e03..f0334d726b 100644 --- a/dwds/test/integration/instances/common/record_type_inspection_common.dart +++ b/dwds_test_common/lib/integration/record_type_inspection.dart @@ -2,22 +2,21 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/integration/test_inspector.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../../fixtures/context.dart'; -import '../../fixtures/project.dart'; -import '../../fixtures/utilities.dart'; -import 'test_inspector.dart'; - void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { - final context = TestContext(TestProject.testExperiment, provider); + final context = contextFactory(TestProject.testExperiment, provider); final testInspector = TestInspector(context); late VmService service; @@ -56,12 +55,11 @@ void runTests({ 'runtimeType': matchTypeClassName, }; - group('$compilationMode |', () { + group('${context.runtimeType} |', () { setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, verboseCompiler: provider.verbose, experiments: ['dot-shorthands'], diff --git a/dwds/test/integration/refresh_common.dart b/dwds_test_common/lib/integration/refresh.dart similarity index 87% rename from dwds/test/integration/refresh_common.dart rename to dwds_test_common/lib/integration/refresh.dart index b4a2f2a65e..c2baae1bba 100644 --- a/dwds/test/integration/refresh_common.dart +++ b/dwds_test_common/lib/integration/refresh.dart @@ -4,18 +4,20 @@ import 'dart:async'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:vm_service_interface/vm_service_interface.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - -void testAll({required TestSdkConfigurationProvider provider}) { - final context = TestContext(TestProject.test, provider); +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final context = contextFactory(TestProject.test, provider); group('fresh context', () { late VmServiceInterface service; diff --git a/dwds/test/integration/run_request_common.dart b/dwds_test_common/lib/integration/run_request.dart similarity index 89% rename from dwds/test/integration/run_request_common.dart rename to dwds_test_common/lib/integration/run_request.dart index 9c35903bcc..b643b614bd 100644 --- a/dwds/test/integration/run_request_common.dart +++ b/dwds_test_common/lib/integration/run_request.dart @@ -4,18 +4,20 @@ import 'dart:async'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; import 'package:vm_service_interface/vm_service_interface.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - -void testAll({required TestSdkConfigurationProvider provider}) { - final context = TestContext(TestProject.test, provider); +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final context = contextFactory(TestProject.test, provider); group('while debugger is attached', () { late VmServiceInterface service; diff --git a/dwds/test/integration/screenshot_common.dart b/dwds_test_common/lib/integration/screenshot.dart similarity index 72% rename from dwds/test/integration/screenshot_common.dart rename to dwds_test_common/lib/integration/screenshot.dart index 4b530a6ffc..231c15bbd2 100644 --- a/dwds/test/integration/screenshot_common.dart +++ b/dwds_test_common/lib/integration/screenshot.dart @@ -2,16 +2,18 @@ // 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:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - -void testAll({required TestSdkConfigurationProvider provider}) { - final context = TestContext(TestProject.test, provider); +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final context = contextFactory(TestProject.test, provider); setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); diff --git a/dwds/test/integration/sdk_configuration_test.dart b/dwds_test_common/lib/integration/sdk_configuration.dart similarity index 94% rename from dwds/test/integration/sdk_configuration_test.dart rename to dwds_test_common/lib/integration/sdk_configuration.dart index bf9014c3a5..d9cc69bb0b 100644 --- a/dwds/test/integration/sdk_configuration_test.dart +++ b/dwds_test_common/lib/integration/sdk_configuration.dart @@ -2,10 +2,6 @@ // 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') -@Timeout(Duration(minutes: 2)) -library; - import 'dart:io'; import 'package:dwds/src/utilities/sdk_configuration.dart'; @@ -22,7 +18,7 @@ var _throwsDoesNotExistException = throwsA( ), ); -void main() { +void runIndependentTests() { group('Basic configuration', () { test('Can validate default configuration layout', () async { final defaultConfiguration = @@ -68,8 +64,9 @@ void main() { final workerDir = p.dirname(compilerWorkerPath); Directory(workerDir).createSync(recursive: true); - File(defaultSdkConfiguration.compilerWorkerPath!) - .copySync(compilerWorkerPath); + File( + defaultSdkConfiguration.compilerWorkerPath!, + ).copySync(compilerWorkerPath); expect(sdkConfiguration.sdkDirectory, equals(sdkDirectory)); expect(sdkConfiguration.sdkSummaryPath, equals(sdkSummaryPath)); @@ -117,11 +114,10 @@ void main() { sdkConfiguration.validate(fileSystem: fs); }); }); +} +void runDependentTests({required TestSdkConfigurationProvider provider}) { group('Test configuration', () { - final provider = TestSdkConfigurationProvider(); - tearDownAll(provider.dispose); - test('Can validate configuration layout with generated assets', () async { final sdkConfiguration = await provider.configuration; sdkConfiguration.validateSdkDir(); diff --git a/dwds/test/integration/instances/common/test_inspector.dart b/dwds_test_common/lib/integration/test_inspector.dart similarity index 99% rename from dwds/test/integration/instances/common/test_inspector.dart rename to dwds_test_common/lib/integration/test_inspector.dart index 4423659911..78426535f8 100644 --- a/dwds/test/integration/instances/common/test_inspector.dart +++ b/dwds_test_common/lib/integration/test_inspector.dart @@ -4,12 +4,11 @@ import 'dart:async' show Completer, StreamSubscription; +import 'package:dwds_test_common/fixtures/context.dart'; import 'package:path/path.dart' show basename; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../../fixtures/context.dart'; - class TestInspector { TestInspector(this.context); TestContext context; diff --git a/dwds/test/integration/instances/common/type_inspection_common.dart b/dwds_test_common/lib/integration/type_inspection.dart similarity index 96% rename from dwds/test/integration/instances/common/type_inspection_common.dart rename to dwds_test_common/lib/integration/type_inspection.dart index cc45462d98..43ecb7bed9 100644 --- a/dwds/test/integration/instances/common/type_inspection_common.dart +++ b/dwds_test_common/lib/integration/type_inspection.dart @@ -3,23 +3,22 @@ // BSD-style license that can be found in the LICENSE file. import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:dwds_test_common/integration/test_inspector.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import '../../fixtures/context.dart'; -import '../../fixtures/project.dart'; -import '../../fixtures/utilities.dart'; -import 'test_inspector.dart'; - void runTests({ required TestSdkConfigurationProvider provider, - required CompilationMode compilationMode, + required TestContextFactory contextFactory, required bool canaryFeatures, }) { final project = TestProject.testExperiment; - final context = TestContext(project, provider); + final context = contextFactory(project, provider); final testInspector = TestInspector(context); late VmService service; @@ -79,12 +78,11 @@ void runTests({ 'runtimeType': matchTypeClassName, }; - group('$compilationMode |', () { + group('${context.runtimeType} |', () { setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); await context.setUp( testSettings: TestSettings( - compilationMode: compilationMode, enableExpressionEvaluation: true, verboseCompiler: provider.verbose, experiments: ['dot-shorthands'], diff --git a/dwds/test/integration/variable_scope_common.dart b/dwds_test_common/lib/integration/variable_scope.dart similarity index 96% rename from dwds/test/integration/variable_scope_common.dart rename to dwds_test_common/lib/integration/variable_scope.dart index a1191aa21b..64038905c5 100644 --- a/dwds/test/integration/variable_scope_common.dart +++ b/dwds_test_common/lib/integration/variable_scope.dart @@ -6,17 +6,19 @@ import 'dart:async'; import 'package:dwds/src/debugging/dart_scope.dart'; import 'package:dwds/src/services/chrome/chrome_proxy_service.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; import 'package:vm_service/vm_service.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; -import 'fixtures/utilities.dart'; - -void testAll({required TestSdkConfigurationProvider provider}) { - final context = TestContext(TestProject.testScopes, provider); +void testAll({ + required TestSdkConfigurationProvider provider, + required TestContextFactory contextFactory, +}) { + final context = contextFactory(TestProject.testScopes, provider); setUpAll(() async { setCurrentLogWriter(debug: provider.verbose); diff --git a/dwds_test_common/lib/sdk_asset_generator.dart b/dwds_test_common/lib/sdk_asset_generator.dart index ea1f06ed01..ec3b4f273d 100644 --- a/dwds_test_common/lib/sdk_asset_generator.dart +++ b/dwds_test_common/lib/sdk_asset_generator.dart @@ -6,6 +6,7 @@ import 'package:file/file.dart'; import 'package:file/local.dart'; import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; + import 'test_sdk_layout.dart'; /// Generates sdk.js, sdk.map, files. diff --git a/dwds_test_common/lib/utilities.dart b/dwds_test_common/lib/utilities.dart index b3c10ac48f..1760ae1285 100644 --- a/dwds_test_common/lib/utilities.dart +++ b/dwds_test_common/lib/utilities.dart @@ -32,33 +32,36 @@ String get fixturesPath { /// root in the local machine, e.g. 'webdev/dwds_test_common' or /// 'pkg/dwds_test_common'. String get _dwdsTestCommonPackageRoot { - final scriptPath = Platform.script.toFilePath(); - final isTest = scriptPath.contains('dart_test.kernel'); - if (isTest) { - // When running tests, p.current might be dwds, so we need to check - // if we're in webdev/dwds_test_common or pkg/dwds_test_common or need to - // navigate to it. - var current = p.current; - if (p.basename(current) == 'dwds') { - // Check if dwds_test_common exists as a sibling - final testCommonPath = p.join(p.dirname(current), 'dwds_test_common'); - if (Directory(testCommonPath).existsSync()) { - return testCommonPath; + // Walk up from Platform.script first + try { + final scriptPath = Platform.script.toFilePath(); + final path = _findTestCommon(scriptPath); + if (path != null) return path; + } catch (_) {} + // Fallback to walking up from p.current + final path = _findTestCommon(p.current); + if (path != null) return path; + throw StateError( + 'Could not find `dwds_test_common` package root from ' + '${Platform.script.path} or ${p.current}.', + ); +} + +String? _findTestCommon(String startPath) { + var current = p.absolute(startPath); + while (current != p.dirname(current)) { + if (p.basename(current) == 'dwds_test_common') { + if (Directory(current).existsSync()) { + return current; } } - return current; // p.current is the package root for tests - } - var current = p.dirname(scriptPath); - while (current != p.dirname(current)) { - if (File(p.join(current, 'pubspec.yaml')).existsSync()) { - return current; // This is the package root + final sibling = p.join(current, 'dwds_test_common'); + if (Directory(sibling).existsSync()) { + return sibling; } current = p.dirname(current); } - throw StateError( - 'Could not find `dwds_test_common` package root from ' - '${Platform.script.path}.', - ); + return null; } // Creates a path compatible for web. diff --git a/dwds_test_common/mono_pkg.yaml b/dwds_test_common/mono_pkg.yaml index 1366dcead6..e3057d9239 100644 --- a/dwds_test_common/mono_pkg.yaml +++ b/dwds_test_common/mono_pkg.yaml @@ -11,6 +11,7 @@ stages: # run first for Linux. - group: - command: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + - command: echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV - test: --exclude-tags=release sdk: dev os: diff --git a/dwds_test_common/pubspec.yaml b/dwds_test_common/pubspec.yaml index e93dd697fe..5be6324fea 100644 --- a/dwds_test_common/pubspec.yaml +++ b/dwds_test_common/pubspec.yaml @@ -6,12 +6,24 @@ environment: sdk: ^3.12.0-0 dependencies: + dds: any dwds: any - file: ">=6.0.0 <8.0.0" - logging: ^1.0.1 - path: ^1.8.1 - pub_semver: ^2.1.1 - test: ^1.21.1 + file: any + http: any + io: any + logging: any + mime: any + package_config: any + path: any + pub_semver: any + shelf: any + shelf_proxy: any + test: any + vm_service: any + vm_service_interface: any + webdriver: any + webkit_inspection_protocol: any + yaml: any dev_dependencies: dart_flutter_team_lints: ^3.5.2 diff --git a/mono_repo.yaml b/mono_repo.yaml index 09f5dee1d1..1fbad800d7 100644 --- a/mono_repo.yaml +++ b/mono_repo.yaml @@ -1,6 +1,8 @@ # See https://pub.dev/packages/mono_repo for details self_validate: analyzer_and_format github: + permissions: + contents: read env: DISPLAY: ':99' cron: '0 0 * * 0' # "At 00:00 (UTC) on Sunday." diff --git a/tool/ci.sh b/tool/ci.sh index 67171c3f9f..22c6b592f7 100755 --- a/tool/ci.sh +++ b/tool/ci.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Created with package:mono_repo v6.6.3 +# Created with package:mono_repo v6.7.2 # Support built in commands on windows out of the box. @@ -71,10 +71,14 @@ for PKG in ${PKGS}; do echo 'dart analyze .' dart analyze . || EXIT_CODE=$? ;; - command) + command_0) echo 'Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &' Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & || EXIT_CODE=$? ;; + command_1) + echo 'echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV' + echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV || EXIT_CODE=$? + ;; format) echo 'dart format --output=none --set-exit-if-changed .' dart format --output=none --set-exit-if-changed . || EXIT_CODE=$? diff --git a/webdev/CHANGELOG.md b/webdev/CHANGELOG.md index fa314c8ce6..6a0e549c19 100644 --- a/webdev/CHANGELOG.md +++ b/webdev/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.1.0-wip + +- Internal test infrastructure refactoring: Move common test files to `dwds_test_common`. + ## 4.0.2 - **Internal**: Resolve Chrome test flakes. diff --git a/webdev/lib/src/serve/webdev_server.dart b/webdev/lib/src/serve/webdev_server.dart index da1f7f2797..309a4adcdd 100644 --- a/webdev/lib/src/serve/webdev_server.dart +++ b/webdev/lib/src/serve/webdev_server.dart @@ -437,7 +437,7 @@ String ddcUriToSourceUrl(String basePath, String target, Uri uri) { /// returns package:some_package/src/sub_dir/file.dart String ddcUriToLibraryId(Uri uri) { final jsPath = uri.isScheme('package') - ? 'package:${uri.path}' + ? 'packages/${uri.path}' : '$multiRootScheme:///${uri.path}'; final prefix = jsPath.substring( 0, diff --git a/webdev/lib/src/version.dart b/webdev/lib/src/version.dart index 1d7ed1f372..78c01d1a64 100644 --- a/webdev/lib/src/version.dart +++ b/webdev/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '4.0.2'; +const packageVersion = '4.1.0-wip'; diff --git a/webdev/mono_pkg.yaml b/webdev/mono_pkg.yaml index 39b1d48dc3..7e1338466a 100644 --- a/webdev/mono_pkg.yaml +++ b/webdev/mono_pkg.yaml @@ -9,6 +9,7 @@ stages: - unit_test: - group: - command: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + - command: echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV - test: -j 1 sdk: dev - test: -j 1 @@ -19,6 +20,7 @@ stages: sdk: beta - group: - command: Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + - command: echo "CHROME_EXECUTABLE=$(which google-chrome)" >> $GITHUB_ENV - test: -j 1 sdk: beta - test: -j 1 diff --git a/webdev/pubspec.yaml b/webdev/pubspec.yaml index f8d1f6c791..b05db3f050 100644 --- a/webdev/pubspec.yaml +++ b/webdev/pubspec.yaml @@ -1,6 +1,6 @@ name: webdev # Every time this changes you need to run `dart run build_runner build`. -version: 4.0.2 +version: 4.1.0-wip # We should not depend on a dev SDK before publishing. # publish_to: none description: >- @@ -57,8 +57,3 @@ executables: webdev: dependency_overrides: - dwds_test_common: - git: - url: https://github.com/dart-lang/sdk.git - ref: cc67fadefe24678e7f020fe42cbb41fed2cd6f0c - path: pkg/dwds_test_common diff --git a/dwds/test/integration/handlers/asset_handler_amd_test.dart b/webdev/test/asset_handler_amd_test.dart similarity index 76% rename from dwds/test/integration/handlers/asset_handler_amd_test.dart rename to webdev/test/asset_handler_amd_test.dart index c5d84ba150..2e8b2dd3de 100644 --- a/dwds/test/integration/handlers/asset_handler_amd_test.dart +++ b/webdev/test/asset_handler_amd_test.dart @@ -6,10 +6,11 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/asset_handler.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'asset_handler_common.dart'; +import 'helpers/context.dart'; void main() { final provider = TestSdkConfigurationProvider( @@ -17,5 +18,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); } diff --git a/dwds/test/integration/handlers/asset_handler_ddc_library_bundle_test.dart b/webdev/test/asset_handler_ddc_library_bundle_test.dart similarity index 79% rename from dwds/test/integration/handlers/asset_handler_ddc_library_bundle_test.dart rename to webdev/test/asset_handler_ddc_library_bundle_test.dart index dbfe9835f4..367d8ce9f6 100644 --- a/dwds/test/integration/handlers/asset_handler_ddc_library_bundle_test.dart +++ b/webdev/test/asset_handler_ddc_library_bundle_test.dart @@ -6,10 +6,11 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/asset_handler.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'asset_handler_common.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -22,5 +23,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); } diff --git a/dwds/test/integration/breakpoint_amd_test.dart b/webdev/test/breakpoint_amd_test.dart similarity index 75% rename from dwds/test/integration/breakpoint_amd_test.dart rename to webdev/test/breakpoint_amd_test.dart index c2b1947a16..43a989f974 100644 --- a/dwds/test/integration/breakpoint_amd_test.dart +++ b/webdev/test/breakpoint_amd_test.dart @@ -7,11 +7,12 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/breakpoint.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'breakpoint_common.dart'; -import 'fixtures/context.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -26,14 +27,14 @@ void main() { group('Build Daemon |', () { testBreakpoint( provider: provider, - compilationMode: CompilationMode.buildDaemon, + contextFactory: BuildDaemonTestContext.new, ); }); group('Frontend Server |', () { testBreakpoint( provider: provider, - compilationMode: CompilationMode.frontendServer, + contextFactory: FrontendServerTestContext.new, ); }); } diff --git a/dwds/test/integration/callstack_amd_test.dart b/webdev/test/callstack_amd_test.dart similarity index 75% rename from dwds/test/integration/callstack_amd_test.dart rename to webdev/test/callstack_amd_test.dart index e511a65e90..1bf5677825 100644 --- a/dwds/test/integration/callstack_amd_test.dart +++ b/webdev/test/callstack_amd_test.dart @@ -7,11 +7,12 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/callstack.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'callstack_common.dart'; -import 'fixtures/context.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -26,14 +27,14 @@ void main() { group('Build Daemon |', () { testCallStack( provider: provider, - compilationMode: CompilationMode.buildDaemon, + contextFactory: BuildDaemonTestContext.new, ); }); group('Frontend Server |', () { testCallStack( provider: provider, - compilationMode: CompilationMode.frontendServer, + contextFactory: FrontendServerTestContext.new, ); }); } diff --git a/dwds/test/integration/chrome_proxy_service_amd_test.dart b/webdev/test/chrome_proxy_service_amd_test.dart similarity index 84% rename from dwds/test/integration/chrome_proxy_service_amd_test.dart rename to webdev/test/chrome_proxy_service_amd_test.dart index fef60fc277..c5e241d660 100644 --- a/dwds/test/integration/chrome_proxy_service_amd_test.dart +++ b/webdev/test/chrome_proxy_service_amd_test.dart @@ -8,18 +8,17 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/chrome_proxy_service.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'common/chrome_proxy_service_common.dart'; -import 'fixtures/context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. const debug = false; final canaryFeatures = false; final moduleFormat = ModuleFormat.amd; - final compilationMode = CompilationMode.buildDaemon; final provider = TestSdkConfigurationProvider( verbose: debug, @@ -33,7 +32,7 @@ void main() { runTests( provider: provider, moduleFormat: moduleFormat, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/circular_evaluate_amd_test.dart b/webdev/test/circular_evaluate_amd_test.dart similarity index 77% rename from dwds/test/integration/circular_evaluate_amd_test.dart rename to webdev/test/circular_evaluate_amd_test.dart index 44d0d5557d..78f2ebd360 100644 --- a/dwds/test/integration/circular_evaluate_amd_test.dart +++ b/webdev/test/circular_evaluate_amd_test.dart @@ -10,12 +10,13 @@ library; import 'dart:io'; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate_circular.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'evaluate_circular_common.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() async { // Enable verbose logging for debugging. @@ -28,7 +29,7 @@ void main() async { tearDownAll(provider.dispose); group('Build Daemon |', () { - testAll(provider: provider, compilationMode: CompilationMode.buildDaemon); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); }); group('Frontend Server |', () { @@ -39,7 +40,7 @@ void main() async { () { testAll( provider: provider, - compilationMode: CompilationMode.frontendServer, + contextFactory: FrontendServerTestContext.new, indexBaseMode: indexBaseMode, useDebuggerModuleNames: true, ); diff --git a/dwds/test/integration/instances/class_inspection_amd_test.dart b/webdev/test/class_inspection_amd_test.dart similarity index 80% rename from dwds/test/integration/instances/class_inspection_amd_test.dart rename to webdev/test/class_inspection_amd_test.dart index dd9102c807..0e2a6a582b 100644 --- a/dwds/test/integration/instances/class_inspection_amd_test.dart +++ b/webdev/test/class_inspection_amd_test.dart @@ -8,11 +8,12 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/class_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/class_inspection_common.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,7 +21,7 @@ void main() { group('canary: false | Build Daemon |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -30,14 +31,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Build Daemon |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,14 +48,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: false | Frontend Server |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -64,14 +65,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -81,7 +82,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); diff --git a/webdev/test/daemon/utils.dart b/webdev/test/daemon/utils.dart index b760eabc44..6909191bb8 100644 --- a/webdev/test/daemon/utils.dart +++ b/webdev/test/daemon/utils.dart @@ -19,18 +19,26 @@ Future exitWebdev(TestProcess webdev) async { } Future waitForAppId(TestProcess webdev) async { - var appId = ''; + final stdoutLines = []; while (await webdev.stdout.hasNext) { var line = await webdev.stdout.next; + stdoutLines.add(line); if (line.startsWith('[{"event":"app.started"')) { line = line.substring(1, line.length - 1); final message = json.decode(line) as Map; - appId = message['params']['appId'] as String; - break; + final appId = message['params']['appId'] as String; + if (appId.isNotEmpty) return appId; } } - assert(appId.isNotEmpty); - return appId; + final stderrLines = []; + while (await webdev.stderr.hasNext) { + stderrLines.add(await webdev.stderr.next); + } + throw StateError( + 'Failed to receive "app.started" event before process stdout closed.\n' + 'Captured stdout:\n${stdoutLines.join('\n')}\n' + 'Captured stderr:\n${stderrLines.join('\n')}', + ); } String? getDebugServiceUri(String line) { diff --git a/webdev/test/dart_uri_file_uri_amd_test.dart b/webdev/test/dart_uri_file_uri_amd_test.dart new file mode 100644 index 0000000000..e3c5e62c6d --- /dev/null +++ b/webdev/test/dart_uri_file_uri_amd_test.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2026, 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') +@Timeout(Duration(minutes: 2)) +library; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/dart_uri_file_uri.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; + +void main() { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.amd, + ); + tearDownAll(provider.dispose); + + group('Build Daemon |', () { + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); + }); + + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/webdev/test/dart_uri_file_uri_ddc_library_bundle_test.dart b/webdev/test/dart_uri_file_uri_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..bf746f988e --- /dev/null +++ b/webdev/test/dart_uri_file_uri_ddc_library_bundle_test.dart @@ -0,0 +1,42 @@ +// Copyright (c) 2026, 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') +@Timeout(Duration(minutes: 2)) +library; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/dart_uri_file_uri.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; + +void main() { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Build Daemon |', () { + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); + }); + + group('Build Daemon and Frontend Server |', () { + testAll( + provider: provider, + contextFactory: BuildDaemonAndFrontendServerTestContext.new, + ); + }); + + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/dwds/test/integration/dds_port_amd_test.dart b/webdev/test/dds_port_amd_test.dart similarity index 73% rename from dwds/test/integration/dds_port_amd_test.dart rename to webdev/test/dds_port_amd_test.dart index 6fbbf45ec6..7fe4ce6425 100644 --- a/dwds/test/integration/dds_port_amd_test.dart +++ b/webdev/test/dds_port_amd_test.dart @@ -6,14 +6,15 @@ @Timeout(Duration(minutes: 2)) library; +import 'package:dwds_test_common/integration/dds_port.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'dds_port_common.dart'; +import 'helpers/context.dart'; void main() { final provider = TestSdkConfigurationProvider(); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); } diff --git a/dwds/test/integration/dds_port_ddc_library_bundle_test.dart b/webdev/test/dds_port_ddc_library_bundle_test.dart similarity index 80% rename from dwds/test/integration/dds_port_ddc_library_bundle_test.dart rename to webdev/test/dds_port_ddc_library_bundle_test.dart index f8125a3e85..77f0e9883c 100644 --- a/dwds/test/integration/dds_port_ddc_library_bundle_test.dart +++ b/webdev/test/dds_port_ddc_library_bundle_test.dart @@ -7,10 +7,11 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/dds_port.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'dds_port_common.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -24,5 +25,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); } diff --git a/dwds/test/integration/debug_service_amd_test.dart b/webdev/test/debug_service_amd_test.dart similarity index 76% rename from dwds/test/integration/debug_service_amd_test.dart rename to webdev/test/debug_service_amd_test.dart index c9b17f24ea..01a3437282 100644 --- a/dwds/test/integration/debug_service_amd_test.dart +++ b/webdev/test/debug_service_amd_test.dart @@ -6,10 +6,11 @@ @Timeout(Duration(minutes: 2)) library; +import 'package:dwds_test_common/integration/debug_service.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'debug_service_common.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -17,5 +18,5 @@ void main() { final provider = TestSdkConfigurationProvider(verbose: debug); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); } diff --git a/dwds/test/integration/devtools_amd_test.dart b/webdev/test/devtools_amd_test.dart similarity index 77% rename from dwds/test/integration/devtools_amd_test.dart rename to webdev/test/devtools_amd_test.dart index 1ce6a598fa..e5e23e9b10 100644 --- a/dwds/test/integration/devtools_amd_test.dart +++ b/webdev/test/devtools_amd_test.dart @@ -7,10 +7,11 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/devtools.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'devtools_common.dart'; +import 'helpers/context.dart'; void main() { final provider = TestSdkConfigurationProvider( @@ -18,5 +19,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); } diff --git a/dwds/test/integration/instances/dot_shorthands_amd_test.dart b/webdev/test/dot_shorthands_amd_test.dart similarity index 80% rename from dwds/test/integration/instances/dot_shorthands_amd_test.dart rename to webdev/test/dot_shorthands_amd_test.dart index 7ae4963827..63227b5171 100644 --- a/dwds/test/integration/instances/dot_shorthands_amd_test.dart +++ b/webdev/test/dot_shorthands_amd_test.dart @@ -8,11 +8,12 @@ library; import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds_test_common/integration/dot_shorthands.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/dot_shorthands_common.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,7 +21,7 @@ void main() { group('canary: false | Build Daemon |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -30,14 +31,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Build Daemon |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,14 +48,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: false | Frontend Server |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -64,14 +65,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -81,7 +82,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/evaluate_amd_test.dart b/webdev/test/evaluate_amd_test.dart similarity index 79% rename from dwds/test/integration/evaluate_amd_test.dart rename to webdev/test/evaluate_amd_test.dart index 5bedc792d9..fdee964cb7 100644 --- a/dwds/test/integration/evaluate_amd_test.dart +++ b/webdev/test/evaluate_amd_test.dart @@ -10,12 +10,13 @@ library; import 'dart:io'; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'evaluate_common.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() async { // Enable verbose logging for debugging. @@ -28,7 +29,7 @@ void main() async { tearDownAll(provider.dispose); group('Build Daemon |', () { - testAll(provider: provider, compilationMode: CompilationMode.buildDaemon); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); }); group('Frontend Server |', () { @@ -40,7 +41,7 @@ void main() async { () { testAll( provider: provider, - compilationMode: CompilationMode.frontendServer, + contextFactory: FrontendServerTestContext.new, indexBaseMode: indexBaseMode, useDebuggerModuleNames: useDebuggerModuleNames, ); diff --git a/dwds/test/integration/events_amd_test.dart b/webdev/test/events_amd_test.dart similarity index 89% rename from dwds/test/integration/events_amd_test.dart rename to webdev/test/events_amd_test.dart index db87a0df45..a15909bad4 100644 --- a/dwds/test/integration/events_amd_test.dart +++ b/webdev/test/events_amd_test.dart @@ -10,12 +10,12 @@ import 'dart:io'; import 'package:dwds/src/events.dart'; import 'package:dwds/src/utilities/server.dart'; +import 'package:dwds_test_common/integration/events.dart'; import 'package:dwds_test_common/logging.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'events_common.dart'; -import 'fixtures/context.dart'; +import 'helpers/context.dart'; void main() { final provider = TestSdkConfigurationProvider(); @@ -78,17 +78,10 @@ void main() { }); }); - group('Frontend Server', () { - testWithDwds( - provider: provider, - compilationMode: CompilationMode.frontendServer, - ); - }); - group('Build Daemon', () { testWithDwds( provider: provider, - compilationMode: CompilationMode.buildDaemon, + contextFactory: BuildDaemonTestContext.new, ); }); } diff --git a/dwds/test/integration/expression_compiler_service_amd_test.dart b/webdev/test/expression_compiler_service_amd_test.dart similarity index 87% rename from dwds/test/integration/expression_compiler_service_amd_test.dart rename to webdev/test/expression_compiler_service_amd_test.dart index 19c8bdc3ae..e4f50a7830 100644 --- a/dwds/test/integration/expression_compiler_service_amd_test.dart +++ b/webdev/test/expression_compiler_service_amd_test.dart @@ -8,10 +8,9 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/expression_compiler_service.dart'; import 'package:test/test.dart'; -import 'expression_compiler_service_common.dart'; - void main() async { testAll( compilerOptions: CompilerOptions( diff --git a/webdev/test/expression_compiler_service_ddc_library_bundle_test.dart b/webdev/test/expression_compiler_service_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..f0955d7cdb --- /dev/null +++ b/webdev/test/expression_compiler_service_ddc_library_bundle_test.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2024, 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. + +@Tags(['daily']) +@TestOn('vm') +@Timeout(Duration(minutes: 2)) +library; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/expression_compiler_service.dart'; +import 'package:test/test.dart'; + +void main() async { + testAll( + compilerOptions: CompilerOptions( + moduleFormat: ModuleFormat.ddc, + canaryFeatures: true, + experiments: const [], + ), + ); +} diff --git a/webdev/test/helpers/context.dart b/webdev/test/helpers/context.dart new file mode 100644 index 0000000000..b3d3248969 --- /dev/null +++ b/webdev/test/helpers/context.dart @@ -0,0 +1,491 @@ +// Copyright (c) 2024, 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:build_daemon/client.dart'; +import 'package:build_daemon/constants.dart'; +import 'package:build_daemon/data/build_status.dart' as daemon; +import 'package:build_daemon/data/build_target.dart'; +import 'package:build_daemon/data/server_log.dart'; +import 'package:dwds/asset_reader.dart'; +import 'package:dwds/data/build_result.dart' as dwds; +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds/src/loaders/build_runner_strategy_provider.dart'; +import 'package:dwds/src/loaders/frontend_server_strategy_provider.dart'; +import 'package:dwds/src/loaders/strategy.dart'; +import 'package:dwds/src/readers/proxy_server_asset_reader.dart'; +import 'package:dwds/src/services/expression_compiler_service.dart'; +import 'package:dwds_test_common/fixtures/context.dart'; +import 'package:dwds_test_common/fixtures/utilities.dart'; +import 'package:file/local.dart'; +import 'package:http/http.dart'; +import 'package:logging/logging.dart' as logging; +import 'package:shelf/shelf.dart'; +import 'package:shelf_proxy/shelf_proxy.dart'; + +Handler createBuildRunnerProxyHandler({ + required String directoryToServe, + required Client client, + required int assetServerPort, +}) { + return proxyHandler( + 'http://localhost:$assetServerPort/$directoryToServe/', + client: client, + ); +} + +mixin BuildDaemonContextMixin on TestContext { + BuildDaemonClient get daemonClient; + + @override + Future waitForSuccessfulBuild({ + Duration? timeout, + bool propagateToBrowser = false, + bool allowFailure = false, + }) async { + final buildStartCompleter = Completer(); + final buildSuccessCompleter = Completer(); + final subscription = daemonClient.buildResults.listen((results) { + final isStartedEvent = results.results.any( + (r) => r.status == daemon.BuildStatus.started, + ); + final isSucceededEvent = results.results.any( + (r) => r.status == daemon.BuildStatus.succeeded, + ); + final isFailedEvent = results.results.any( + (r) => r.status == daemon.BuildStatus.failed, + ); + + if (isStartedEvent) { + if (!buildStartCompleter.isCompleted) buildStartCompleter.complete(); + } + if (isFailedEvent) { + if (!buildSuccessCompleter.isCompleted) { + final failedResult = results.results.firstWhere( + (r) => r.status == daemon.BuildStatus.failed, + ); + final daemonError = + failedResult.error ?? 'Unknown daemon compilation error'; + if (allowFailure) { + buildSuccessCompleter.complete(); + } else { + buildSuccessCompleter.completeError( + StateError('Build daemon build failed.\nError: $daemonError'), + ); + } + } + } + if (buildStartCompleter.isCompleted && isSucceededEvent) { + if (!buildSuccessCompleter.isCompleted) { + buildSuccessCompleter.complete(); + } + } + }); + + var isWaitingForSuccess = false; + try { + var timedOutWaitingForStart = false; + await buildStartCompleter.future.timeout( + const Duration(seconds: 5), + onTimeout: () { + timedOutWaitingForStart = true; + }, + ); + + if (timedOutWaitingForStart) { + return; + } + + isWaitingForSuccess = true; + await buildSuccessCompleter.future.timeout( + timeout ?? const Duration(seconds: 60), + ); + } catch (e) { + if (e is TimeoutException) { + // Return if an edit did not trigger a rebuild/recompile. + if (!isWaitingForSuccess) { + return; + } + // If the build started but never finished, the test has likely hung. + rethrow; + } + rethrow; + } finally { + await subscription.cancel(); + } + + if (propagateToBrowser) { + final delay = Platform.isWindows + ? const Duration(seconds: 5) + : const Duration(seconds: 2); + await Future.delayed(delay); + } + } +} + +class BuildDaemonTestContext extends TestContext with BuildDaemonContextMixin { + final _logger = logging.Logger('BuildDaemonTestContext'); + + BuildDaemonTestContext(super.project, super.sdkConfigurationProvider) + : super.protected(); + + late AssetReader _assetReader; + late Handler _assetHandler; + late LoadStrategy _loadStrategy; + late Stream _buildResults; + ExpressionCompiler? _expressionCompiler; + + @override + late BuildDaemonClient daemonClient; + ExpressionCompilerService? ddcService; + + @override + AssetReader get assetReader => _assetReader; + @override + Handler get assetHandler => _assetHandler; + @override + LoadStrategy get loadStrategy => _loadStrategy; + @override + Stream get buildResults => _buildResults; + @override + ExpressionCompiler? get expressionCompiler => _expressionCompiler; + + @override + bool get usesFrontendServer => false; + @override + bool get usesBuildDaemon => true; + @override + bool get usesDdcModulesOnly => false; + + @override + String get appUrlPath => project.filePathToServe; + + @override + Future modeSetUp( + TestSettings testSettings, + TestDebugSettings debugSettings, + TestAppMetadata appMetadata, + Uri reloadedSourcesUri, + ) async { + final sdkLayout = sdkConfigurationProvider.sdkLayout; + final buildSettings = TestBuildSettings( + appEntrypoint: project.dartEntryFilePackageUri, + canaryFeatures: testSettings.canaryFeatures, + isFlutterApp: testSettings.isFlutterApp, + experiments: testSettings.experiments, + ); + + final options = [ + if (testSettings.enableExpressionEvaluation) ...[ + '--define', + 'build_web_compilers|ddc=generate-full-dill=true', + ], + for (final experiment in buildSettings.experiments) + '--enable-experiment=$experiment', + if (buildSettings.canaryFeatures) ...[ + '--define', + 'build_web_compilers|ddc=canary=true', + '--define', + 'build_web_compilers|sdk_js=canary=true', + ], + if (testSettings.moduleFormat == ModuleFormat.ddc) ...[ + '--define', + 'build_web_compilers|ddc=ddc-library-bundle=true', + '--define', + 'build_web_compilers|sdk_js=ddc-library-bundle=true', + '--define', + 'build_web_compilers|entrypoint=ddc-library-bundle=true', + '--define', + 'build_web_compilers|entrypoint_marker=ddc-library-bundle=true', + ], + '--verbose', + ]; + daemonClient = await connectClient( + sdkLayout.dartPath, + project.absolutePackageDirectory, + options, + (log) { + final record = log.toLogRecord(); + final name = record.loggerName == '' ? '' : '${record.loggerName}: '; + _logger.log( + record.level, + '$name${record.message}', + record.error, + record.stackTrace, + ); + }, + ); + daemonClient.registerBuildTarget( + DefaultBuildTarget((b) => b..target = project.directoryToServe), + ); + daemonClient.startBuild(); + + await waitForSuccessfulBuild(); + + final assetServerPort = daemonPort(project.absolutePackageDirectory); + _assetHandler = createBuildRunnerProxyHandler( + directoryToServe: project.directoryToServe, + client: client, + assetServerPort: assetServerPort, + ); + if (testSettings.moduleFormat == ModuleFormat.ddc && + buildSettings.canaryFeatures) { + _assetHandler = handleReloadedSources(_assetHandler); + } + _assetReader = ProxyServerAssetReader( + assetServerPort, + root: project.directoryToServe, + ); + + if (testSettings.enableExpressionEvaluation) { + ddcService = ExpressionCompilerService( + 'localhost', + port, + verbose: testSettings.verboseCompiler, + sdkConfigurationProvider: sdkConfigurationProvider, + ); + _expressionCompiler = ddcService; + } else { + _expressionCompiler = null; + } + + _loadStrategy = switch (( + testSettings.moduleFormat, + buildSettings.canaryFeatures, + )) { + (ModuleFormat.ddc, true) => BuildRunnerDdcLibraryBundleStrategyProvider( + testSettings.reloadConfiguration, + _assetReader, + buildSettings, + reloadedSourcesUri: reloadedSourcesUri, + ).strategy, + (ModuleFormat.ddc, false) => throw Exception( + 'Unsupported DDC configuration: build daemon + canary (false) ' + '+ DDC module format ${testSettings.moduleFormat.name}.', + ), + _ => BuildRunnerRequireStrategyProvider( + testSettings.reloadConfiguration, + _assetReader, + buildSettings, + ).strategy, + }; + + _buildResults = daemonClient.buildResults.map((results) { + final result = results.results.firstWhere( + (result) => result.target == project.directoryToServe, + ); + switch (result.status) { + case daemon.BuildStatus.started: + return dwds.BuildResult(status: dwds.BuildStatus.started); + case daemon.BuildStatus.failed: + return dwds.BuildResult(status: dwds.BuildStatus.failed); + case daemon.BuildStatus.succeeded: + return dwds.BuildResult(status: dwds.BuildStatus.succeeded); + } + throw StateError('Unexpected Daemon build result: $result'); + }); + } + + @override + Future modeTearDown() async { + await ddcService?.stop(); + ddcService = null; + _expressionCompiler = null; + try { + await daemonClient.close(); + } catch (_) {} + } +} + +class BuildDaemonAndFrontendServerTestContext extends TestContext + with BuildDaemonContextMixin { + final _logger = logging.Logger('BuildDaemonAndFrontendServerTestContext'); + + BuildDaemonAndFrontendServerTestContext( + super.project, + super.sdkConfigurationProvider, + ) : super.protected(); + + late AssetReader _assetReader; + late Handler _assetHandler; + late LoadStrategy _loadStrategy; + late Stream _buildResults; + ExpressionCompiler? _expressionCompiler; + + @override + late BuildDaemonClient daemonClient; + ExpressionCompilerService? ddcService; + late LocalFileSystem frontendServerFileSystem; + + @override + AssetReader get assetReader => _assetReader; + @override + Handler get assetHandler => _assetHandler; + @override + LoadStrategy get loadStrategy => _loadStrategy; + @override + Stream get buildResults => _buildResults; + @override + ExpressionCompiler? get expressionCompiler => _expressionCompiler; + + @override + bool get usesFrontendServer => true; + @override + bool get usesBuildDaemon => true; + @override + bool get usesDdcModulesOnly => true; + + @override + String get appUrlPath => project.filePathToServe; + + @override + Future modeSetUp( + TestSettings testSettings, + TestDebugSettings debugSettings, + TestAppMetadata appMetadata, + Uri reloadedSourcesUri, + ) async { + final sdkLayout = sdkConfigurationProvider.sdkLayout; + final buildSettings = TestBuildSettings( + appEntrypoint: project.dartEntryFilePackageUri, + canaryFeatures: testSettings.canaryFeatures, + isFlutterApp: testSettings.isFlutterApp, + experiments: testSettings.experiments, + ); + + final options = [ + if (testSettings.enableExpressionEvaluation) ...[ + '--define', + 'build_web_compilers|ddc=generate-full-dill=true', + ], + for (final experiment in buildSettings.experiments) + '--enable-experiment=$experiment', + '--define', + 'build_web_compilers|ddc=canary=true', + '--define', + 'build_web_compilers|sdk_js=canary=true', + '--define', + 'build_web_compilers|sdk_js=web-hot-reload=true', + '--define', + 'build_web_compilers|entrypoint=web-hot-reload=true', + '--define', + 'build_web_compilers|entrypoint_marker=web-hot-reload=true', + '--define', + 'build_web_compilers|entrypoint_marker=web-assets-path=' + '${project.webAssetsPath}', + '--define', + 'build_web_compilers|ddc=web-hot-reload=true', + '--define', + 'build_web_compilers|ddc_modules=web-hot-reload=true', + '--verbose', + ]; + daemonClient = await connectClient( + sdkLayout.dartPath, + project.absolutePackageDirectory, + options, + (log) { + final record = log.toLogRecord(); + final name = record.loggerName == '' ? '' : '${record.loggerName}: '; + _logger.log( + record.level, + '$name${record.message}', + record.error, + record.stackTrace, + ); + }, + ); + daemonClient.registerBuildTarget( + DefaultBuildTarget((b) => b..target = project.directoryToServe), + ); + daemonClient.startBuild(); + + await waitForSuccessfulBuild(); + + final assetServerPort = daemonPort(project.absolutePackageDirectory); + _assetHandler = createBuildRunnerProxyHandler( + directoryToServe: project.directoryToServe, + client: client, + assetServerPort: assetServerPort, + ); + if (testSettings.moduleFormat == ModuleFormat.ddc && + buildSettings.canaryFeatures) { + _assetHandler = handleReloadedSources(_assetHandler); + } + _assetReader = ProxyServerAssetReader( + assetServerPort, + root: project.directoryToServe, + ); + + if (testSettings.enableExpressionEvaluation) { + ddcService = ExpressionCompilerService( + 'localhost', + port, + verbose: testSettings.verboseCompiler, + sdkConfigurationProvider: sdkConfigurationProvider, + ); + _expressionCompiler = ddcService; + } + frontendServerFileSystem = const LocalFileSystem(); + final packageUriMapper = await PackageUriMapper.create( + frontendServerFileSystem, + project.packageConfigFile, + useDebuggerModuleNames: testSettings.useDebuggerModuleNames, + ); + _loadStrategy = switch (( + testSettings.moduleFormat, + buildSettings.canaryFeatures, + )) { + (ModuleFormat.ddc, true) => + FrontendServerDdcLibraryBundleStrategyProvider( + testSettings.reloadConfiguration, + _assetReader, + packageUriMapper, + () async => {}, + buildSettings, + injectScriptLoad: false, + reloadedSourcesUri: reloadedSourcesUri, + ).strategy, + _ => throw Exception( + 'Unsupported DDC module format when compiling with Frontend ' + 'Server + build_runner ${testSettings.moduleFormat.name}.', + ), + }; + _buildResults = const Stream.empty(); + } + + @override + Future modeTearDown() async { + await ddcService?.stop(); + try { + await daemonClient.close(); + } catch (_) {} + } +} + +/// Connects to the `build_runner` daemon. +Future connectClient( + String dartPath, + String workingDirectory, + List options, + void Function(ServerLog) logHandler, +) => BuildDaemonClient.connect(workingDirectory, [ + dartPath, + 'run', + 'build_runner', + 'daemon', + ...options, +], logHandler: logHandler); + +/// Returns the port of the daemon asset server. +int daemonPort(String workingDirectory) { + final portFile = File(_assetServerPortFilePath(workingDirectory)); + if (!portFile.existsSync()) { + throw Exception('Unable to read daemon asset port file.'); + } + return int.parse(portFile.readAsStringSync()); +} + +String _assetServerPortFilePath(String workingDirectory) => + '${daemonWorkspace(workingDirectory)}/.asset_server_port'; diff --git a/dwds/test/integration/hot_restart_amd_test.dart b/webdev/test/hot_restart_amd_test.dart similarity index 83% rename from dwds/test/integration/hot_restart_amd_test.dart rename to webdev/test/hot_restart_amd_test.dart index 8e1bb8320f..8cc3b784ef 100644 --- a/dwds/test/integration/hot_restart_amd_test.dart +++ b/webdev/test/hot_restart_amd_test.dart @@ -8,18 +8,17 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/hot_restart.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'common/hot_restart_common.dart'; -import 'fixtures/context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. const debug = false; final canaryFeatures = false; final moduleFormat = ModuleFormat.amd; - final compilationMode = CompilationMode.buildDaemon; final provider = TestSdkConfigurationProvider( verbose: debug, @@ -30,7 +29,7 @@ void main() { runTests( provider: provider, moduleFormat: moduleFormat, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); } diff --git a/dwds/test/integration/hot_restart_correctness_amd_test.dart b/webdev/test/hot_restart_correctness_amd_test.dart similarity index 82% rename from dwds/test/integration/hot_restart_correctness_amd_test.dart rename to webdev/test/hot_restart_correctness_amd_test.dart index e034ff3afb..9d8170775e 100644 --- a/dwds/test/integration/hot_restart_correctness_amd_test.dart +++ b/webdev/test/hot_restart_correctness_amd_test.dart @@ -8,18 +8,17 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/hot_restart_correctness.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'common/hot_restart_correctness_common.dart'; -import 'fixtures/context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. const debug = false; final canaryFeatures = false; final moduleFormat = ModuleFormat.amd; - final compilationMode = CompilationMode.buildDaemon; final provider = TestSdkConfigurationProvider( verbose: debug, @@ -30,7 +29,7 @@ void main() { runTests( provider: provider, moduleFormat: moduleFormat, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); } diff --git a/webdev/test/inspector_amd_test.dart b/webdev/test/inspector_amd_test.dart new file mode 100644 index 0000000000..83ec20aa0a --- /dev/null +++ b/webdev/test/inspector_amd_test.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2026, 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') +@Timeout(Duration(minutes: 2)) +library; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/inspector.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; + +void main() { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.amd, + ); + tearDownAll(provider.dispose); + + group('Frontend Server |', () { + runTests(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/dwds/test/integration/callstack_ddc_library_bundle_test.dart b/webdev/test/inspector_ddc_library_bundle_test.dart similarity index 69% rename from dwds/test/integration/callstack_ddc_library_bundle_test.dart rename to webdev/test/inspector_ddc_library_bundle_test.dart index 3344150622..d25e262e32 100644 --- a/dwds/test/integration/callstack_ddc_library_bundle_test.dart +++ b/webdev/test/inspector_ddc_library_bundle_test.dart @@ -7,11 +7,11 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/inspector.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'callstack_common.dart'; -import 'fixtures/context.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; void main() { // Enable verbose logging for debugging. @@ -24,17 +24,7 @@ void main() { ); tearDownAll(provider.dispose); - group('Build Daemon |', () { - testCallStack( - provider: provider, - compilationMode: CompilationMode.buildDaemon, - ); - }); - group('Frontend Server |', () { - testCallStack( - provider: provider, - compilationMode: CompilationMode.frontendServer, - ); + runTests(provider: provider, contextFactory: FrontendServerTestContext.new); }); } diff --git a/dwds/test/integration/instances/instance_amd_test.dart b/webdev/test/instance_amd_test.dart similarity index 79% rename from dwds/test/integration/instances/instance_amd_test.dart rename to webdev/test/instance_amd_test.dart index af28c889cb..4187c060e1 100644 --- a/dwds/test/integration/instances/instance_amd_test.dart +++ b/webdev/test/instance_amd_test.dart @@ -7,11 +7,12 @@ library; import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds_test_common/integration/instance.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/instance_common.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,7 +21,7 @@ void main() { group('canary: false | Build Daemon |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( canaryFeatures: canaryFeatures, verbose: debug, @@ -30,20 +31,20 @@ void main() { runTypeSystemVerificationTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Build Daemon |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( canaryFeatures: canaryFeatures, verbose: debug, @@ -53,20 +54,20 @@ void main() { runTypeSystemVerificationTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: false | Frontend Server |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( canaryFeatures: canaryFeatures, verbose: debug, @@ -76,20 +77,20 @@ void main() { runTypeSystemVerificationTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( canaryFeatures: canaryFeatures, verbose: debug, @@ -99,13 +100,13 @@ void main() { runTypeSystemVerificationTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/instance_inspection_amd_test.dart b/webdev/test/instance_inspection_amd_test.dart similarity index 80% rename from dwds/test/integration/instances/instance_inspection_amd_test.dart rename to webdev/test/instance_inspection_amd_test.dart index 1d526c53f0..fcf614a405 100644 --- a/dwds/test/integration/instances/instance_inspection_amd_test.dart +++ b/webdev/test/instance_inspection_amd_test.dart @@ -8,11 +8,12 @@ library; import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds_test_common/integration/instance_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/instance_inspection_common.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,7 +21,7 @@ void main() { group('canary: false | Build Daemon |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -30,14 +31,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Build Daemon |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,14 +48,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: false | Frontend Server |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -64,14 +65,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -81,7 +82,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/events_ddc_library_bundle_test.dart b/webdev/test/listviews_amd_test.dart similarity index 57% rename from dwds/test/integration/events_ddc_library_bundle_test.dart rename to webdev/test/listviews_amd_test.dart index 4f850e22a6..4349147e5e 100644 --- a/dwds/test/integration/events_ddc_library_bundle_test.dart +++ b/webdev/test/listviews_amd_test.dart @@ -2,38 +2,33 @@ // 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') @Timeout(Duration(minutes: 2)) library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/listviews.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'events_common.dart'; -import 'fixtures/context.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. const debug = false; - final canary = true; + final provider = TestSdkConfigurationProvider( verbose: debug, - canaryFeatures: canary, - ddcModuleFormat: ModuleFormat.ddc, + ddcModuleFormat: ModuleFormat.amd, ); tearDownAll(provider.dispose); - group('Frontend Server', () { - testWithDwds( - provider: provider, - compilationMode: CompilationMode.frontendServer, - ); + group('Build Daemon |', () { + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); }); - group('Build Daemon', () { - testWithDwds( - provider: provider, - compilationMode: CompilationMode.buildDaemon, - ); + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); }); } diff --git a/webdev/test/listviews_ddc_library_bundle_test.dart b/webdev/test/listviews_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..e465d7587e --- /dev/null +++ b/webdev/test/listviews_ddc_library_bundle_test.dart @@ -0,0 +1,42 @@ +// Copyright (c) 2026, 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') +@Timeout(Duration(minutes: 2)) +library; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/listviews.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; + +void main() { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Build Daemon |', () { + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); + }); + + group('Build Daemon and Frontend Server |', () { + testAll( + provider: provider, + contextFactory: BuildDaemonAndFrontendServerTestContext.new, + ); + }); + + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/webdev/test/load_strategy_amd_test.dart b/webdev/test/load_strategy_amd_test.dart new file mode 100644 index 0000000000..3d6bf20cdf --- /dev/null +++ b/webdev/test/load_strategy_amd_test.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2026, 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') +@Timeout(Duration(minutes: 2)) +library; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/load_strategy.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; + +void main() { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.amd, + ); + tearDownAll(provider.dispose); + + group('Build Daemon |', () { + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); + }); + + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/webdev/test/load_strategy_ddc_library_bundle_test.dart b/webdev/test/load_strategy_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..283280b2d5 --- /dev/null +++ b/webdev/test/load_strategy_ddc_library_bundle_test.dart @@ -0,0 +1,42 @@ +// Copyright (c) 2026, 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') +@Timeout(Duration(minutes: 2)) +library; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/load_strategy.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; + +void main() { + // Enable verbose logging for debugging. + const debug = false; + + final provider = TestSdkConfigurationProvider( + verbose: debug, + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + group('Build Daemon |', () { + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); + }); + + group('Build Daemon and Frontend Server |', () { + testAll( + provider: provider, + contextFactory: BuildDaemonAndFrontendServerTestContext.new, + ); + }); + + group('Frontend Server |', () { + testAll(provider: provider, contextFactory: FrontendServerTestContext.new); + }); +} diff --git a/dwds/test/integration/parts_evaluate_amd_test.dart b/webdev/test/parts_evaluate_amd_test.dart similarity index 77% rename from dwds/test/integration/parts_evaluate_amd_test.dart rename to webdev/test/parts_evaluate_amd_test.dart index 132ae9bcce..439dddc2aa 100644 --- a/dwds/test/integration/parts_evaluate_amd_test.dart +++ b/webdev/test/parts_evaluate_amd_test.dart @@ -10,12 +10,13 @@ library; import 'dart:io'; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/fixtures/project.dart'; +import 'package:dwds_test_common/integration/evaluate_parts.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'evaluate_parts_common.dart'; -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() async { // Enable verbose logging for debugging. @@ -28,7 +29,7 @@ void main() async { tearDownAll(provider.dispose); group('Build Daemon |', () { - testAll(provider: provider, compilationMode: CompilationMode.buildDaemon); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); }); group('Frontend Server |', () { @@ -39,7 +40,7 @@ void main() async { () { testAll( provider: provider, - compilationMode: CompilationMode.frontendServer, + contextFactory: FrontendServerTestContext.new, indexBaseMode: indexBaseMode, useDebuggerModuleNames: true, ); diff --git a/dwds/test/integration/instances/patterns_inspection_amd_test.dart b/webdev/test/patterns_inspection_amd_test.dart similarity index 80% rename from dwds/test/integration/instances/patterns_inspection_amd_test.dart rename to webdev/test/patterns_inspection_amd_test.dart index cb52f7307f..09d1eeaccc 100644 --- a/dwds/test/integration/instances/patterns_inspection_amd_test.dart +++ b/webdev/test/patterns_inspection_amd_test.dart @@ -8,11 +8,12 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/patterns_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/patterns_inspection_common.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,7 +21,7 @@ void main() { group('canary: false | Build Daemon |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -30,14 +31,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Build Daemon |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,14 +48,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: false | Frontend Server |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -64,14 +65,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -81,7 +82,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); diff --git a/webdev/test/proxy_server_asset_reader_amd_test.dart b/webdev/test/proxy_server_asset_reader_amd_test.dart new file mode 100644 index 0000000000..88b2339b4a --- /dev/null +++ b/webdev/test/proxy_server_asset_reader_amd_test.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2026, 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. + +@Timeout(Duration(minutes: 2)) +library; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/readers/proxy_server_asset_reader.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import 'helpers/context.dart'; + +void main() { + final provider = TestSdkConfigurationProvider( + ddcModuleFormat: ModuleFormat.amd, + ); + tearDownAll(provider.dispose); + + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); +} diff --git a/webdev/test/proxy_server_asset_reader_ddc_library_bundle_test.dart b/webdev/test/proxy_server_asset_reader_ddc_library_bundle_test.dart new file mode 100644 index 0000000000..5791aee05c --- /dev/null +++ b/webdev/test/proxy_server_asset_reader_ddc_library_bundle_test.dart @@ -0,0 +1,23 @@ +// Copyright (c) 2026, 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. + +@Timeout(Duration(minutes: 2)) +library; + +import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/readers/proxy_server_asset_reader.dart'; +import 'package:dwds_test_common/test_sdk_configuration.dart'; +import 'package:test/test.dart'; + +import 'helpers/context.dart'; + +void main() { + final provider = TestSdkConfigurationProvider( + ddcModuleFormat: ModuleFormat.ddc, + canaryFeatures: true, + ); + tearDownAll(provider.dispose); + + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); +} diff --git a/dwds/test/integration/instances/record_inspection_amd_test.dart b/webdev/test/record_inspection_amd_test.dart similarity index 80% rename from dwds/test/integration/instances/record_inspection_amd_test.dart rename to webdev/test/record_inspection_amd_test.dart index 0cd64a97ee..b6e0e8f4f5 100644 --- a/dwds/test/integration/instances/record_inspection_amd_test.dart +++ b/webdev/test/record_inspection_amd_test.dart @@ -8,11 +8,12 @@ library; import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds_test_common/integration/record_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/record_inspection_common.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,7 +21,7 @@ void main() { group('canary: false | Build Daemon |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -30,14 +31,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Build Daemon |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,14 +48,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: false | Frontend Server |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -64,14 +65,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -81,7 +82,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/instances/record_type_inspection_amd_test.dart b/webdev/test/record_type_inspection_amd_test.dart similarity index 80% rename from dwds/test/integration/instances/record_type_inspection_amd_test.dart rename to webdev/test/record_type_inspection_amd_test.dart index 618ef53ed1..8129517cfb 100644 --- a/dwds/test/integration/instances/record_type_inspection_amd_test.dart +++ b/webdev/test/record_type_inspection_amd_test.dart @@ -8,11 +8,12 @@ library; import 'package:dwds/src/services/expression_compiler.dart'; +import 'package:dwds_test_common/integration/record_type_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/record_type_inspection_common.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,7 +21,7 @@ void main() { group('canary: false | Build Daemon |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -30,14 +31,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Build Daemon |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,14 +48,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: false | Frontend Server |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -64,14 +65,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -81,7 +82,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/refresh_amd_test.dart b/webdev/test/refresh_amd_test.dart similarity index 77% rename from dwds/test/integration/refresh_amd_test.dart rename to webdev/test/refresh_amd_test.dart index f4ffaffe92..cbf6125e84 100644 --- a/dwds/test/integration/refresh_amd_test.dart +++ b/webdev/test/refresh_amd_test.dart @@ -8,14 +8,15 @@ @Timeout(Duration(minutes: 2)) library; +import 'package:dwds_test_common/integration/refresh.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'refresh_common.dart'; +import 'helpers/context.dart'; void main() { final provider = TestSdkConfigurationProvider(); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); } diff --git a/dwds/test/integration/run_request_amd_test.dart b/webdev/test/run_request_amd_test.dart similarity index 78% rename from dwds/test/integration/run_request_amd_test.dart rename to webdev/test/run_request_amd_test.dart index 4f1edd356e..83524eccf0 100644 --- a/dwds/test/integration/run_request_amd_test.dart +++ b/webdev/test/run_request_amd_test.dart @@ -6,10 +6,11 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/run_request.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'run_request_common.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -21,5 +22,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); } diff --git a/dwds/test/integration/screenshot_amd_test.dart b/webdev/test/screenshot_amd_test.dart similarity index 76% rename from dwds/test/integration/screenshot_amd_test.dart rename to webdev/test/screenshot_amd_test.dart index 771e205bd3..74a492450e 100644 --- a/dwds/test/integration/screenshot_amd_test.dart +++ b/webdev/test/screenshot_amd_test.dart @@ -6,10 +6,11 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/screenshot.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'screenshot_common.dart'; +import 'helpers/context.dart'; void main() { final provider = TestSdkConfigurationProvider( @@ -17,5 +18,5 @@ void main() { ); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); } diff --git a/dwds/test/integration/readers/proxy_server_asset_reader_amd_test.dart b/webdev/test/sdk_configuration_amd_test.dart similarity index 74% rename from dwds/test/integration/readers/proxy_server_asset_reader_amd_test.dart rename to webdev/test/sdk_configuration_amd_test.dart index e7d2d05592..9d4102c48d 100644 --- a/dwds/test/integration/readers/proxy_server_asset_reader_amd_test.dart +++ b/webdev/test/sdk_configuration_amd_test.dart @@ -2,20 +2,23 @@ // 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') @Timeout(Duration(minutes: 2)) library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/sdk_configuration.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'proxy_server_asset_reader_common.dart'; - void main() { + // Run independent tests once. + runIndependentTests(); + final provider = TestSdkConfigurationProvider( ddcModuleFormat: ModuleFormat.amd, ); tearDownAll(provider.dispose); - testAll(provider: provider); + runDependentTests(provider: provider); } diff --git a/dwds/test/integration/readers/proxy_server_asset_reader_ddc_library_bundle_test.dart b/webdev/test/sdk_configuration_ddc_library_bundle_test.dart similarity index 75% rename from dwds/test/integration/readers/proxy_server_asset_reader_ddc_library_bundle_test.dart rename to webdev/test/sdk_configuration_ddc_library_bundle_test.dart index ee42cfd2d0..dd8c72d7a8 100644 --- a/dwds/test/integration/readers/proxy_server_asset_reader_ddc_library_bundle_test.dart +++ b/webdev/test/sdk_configuration_ddc_library_bundle_test.dart @@ -2,21 +2,24 @@ // 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') @Timeout(Duration(minutes: 2)) library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/sdk_configuration.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'proxy_server_asset_reader_common.dart'; - void main() { + // Run independent tests once. + runIndependentTests(); + final provider = TestSdkConfigurationProvider( ddcModuleFormat: ModuleFormat.ddc, canaryFeatures: true, ); tearDownAll(provider.dispose); - testAll(provider: provider); + runDependentTests(provider: provider); } diff --git a/dwds/test/integration/instances/type_inspection_amd_test.dart b/webdev/test/type_inspection_amd_test.dart similarity index 80% rename from dwds/test/integration/instances/type_inspection_amd_test.dart rename to webdev/test/type_inspection_amd_test.dart index 717952e2b2..6e40ecd537 100644 --- a/dwds/test/integration/instances/type_inspection_amd_test.dart +++ b/webdev/test/type_inspection_amd_test.dart @@ -8,11 +8,12 @@ library; import 'package:dwds/expression_compiler.dart'; +import 'package:dwds_test_common/integration/type_inspection.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import '../fixtures/context.dart'; -import 'common/type_inspection_common.dart'; +import '../../dwds/test/integration/fixtures/frontend_server_context.dart'; +import 'helpers/context.dart'; void main() { // Enable verbose logging for debugging. @@ -20,7 +21,7 @@ void main() { group('canary: false | Build Daemon |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -30,14 +31,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Build Daemon |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.buildDaemon; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -47,14 +48,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: BuildDaemonTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: false | Frontend Server |', () { final canaryFeatures = false; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -64,14 +65,14 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); group('canary: true | Frontend Server |', () { final canaryFeatures = true; - final compilationMode = CompilationMode.frontendServer; + final provider = TestSdkConfigurationProvider( verbose: debug, canaryFeatures: canaryFeatures, @@ -81,7 +82,7 @@ void main() { runTests( provider: provider, - compilationMode: compilationMode, + contextFactory: FrontendServerTestContext.new, canaryFeatures: canaryFeatures, ); }); diff --git a/dwds/test/integration/variable_scope_amd_test.dart b/webdev/test/variable_scope_amd_test.dart similarity index 75% rename from dwds/test/integration/variable_scope_amd_test.dart rename to webdev/test/variable_scope_amd_test.dart index f4d562f87a..c27d593ce9 100644 --- a/dwds/test/integration/variable_scope_amd_test.dart +++ b/webdev/test/variable_scope_amd_test.dart @@ -6,10 +6,11 @@ @Timeout(Duration(minutes: 2)) library; +import 'package:dwds_test_common/integration/variable_scope.dart'; import 'package:dwds_test_common/test_sdk_configuration.dart'; import 'package:test/test.dart'; -import 'variable_scope_common.dart'; +import 'helpers/context.dart'; void main() { // set to true for debug logging. @@ -18,5 +19,5 @@ void main() { final provider = TestSdkConfigurationProvider(verbose: debug); tearDownAll(provider.dispose); - testAll(provider: provider); + testAll(provider: provider, contextFactory: BuildDaemonTestContext.new); }